% \iffalse meta-comment % arara: lualatex: { branch: developer, draft: true } % arara: clean: { files: [ enumext-01.pdf, enumext-02.pdf, enumext-03.pdf, enumext-04.pdf, enumext-05.pdf ] } % arara: lualatex: { branch: developer, shell: true } % arara: clean: { extensions: [ aux, log, out, glo, gls, hd, ind, ilg, idx, toc, atfi ] } % arara: clean: { files: [ userdoc.idx, userdoc.ilg, userdoc.ind ] } % arara: halt % % File: enumext.dtx % % Copyright (C) 2024 by Pablo González L % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3c of this license or (at % your option) any later version. The latest version of this license is in % % https://www.latex-project.org/lppl.txt % % and version 1.3c or later is part of all distributions of LaTeX version % 2005/12/01 or later. % % This work is "maintained" (as per the LPPL maintenance status) % by Pablo González Luengo. % % This work consists of the files enumext.dtx and enumext.sty. % % \fi % % \iffalse %<*driver> \documentclass[full]{l3doc} % Remove `"` and `|` for short verbatim defined in l3doc, then set short |...| \AtBeginDocument { \DeleteShortVerb \" \DeleteShortVerb \| \lstMakeShortInline[language=enumext-doc,basicstyle=\ttfamily]\| } % imakeidx also opens a write stream for the .idx file, and that conflicts % with the one opened by l3doc. Here we close that write stream: \makeatletter \immediate\closeout\@indexfile \makeatother % and later we will copy the write stream opened by imakeidx into \@indexfile % so that entries written to both streams end up in the same file. \usepackage[english]{babel} \usepackage[top=0.5in,bottom=0.3in,left=1.70in,right=0.7in,footskip=0.2in,headheight=1cm,headsep=0.27cm]{geometry} \usepackage[osf,nomath,mono=false,ScaleSF=0.95,ScaleRM=0.95]{libertinus-otf} % Set Monospace font, fix 'quotes' in verbatim \usepackage{sourcecodepro} \defaultfontfeatures[\ttfamily] { Numbers = OldStyle, Scale = 0.84249, Extension = .otf, } \setmonofont[ UprightFont = *-Regular, ItalicFont = *-RegularIt, BoldFont = *-Semibold, BoldItalicFont = *-SemiboldIt, RawFeature = {+zero,+ss01}]{SourceCodePro} \newfontfamily\mysourcecodeprolight{SourceCodePro-Regular.otf}[ Scale = 0.80,FakeStretch =0.75, FontFace = {m}{it}{Font =SourceCodePro-RegularIt.otf,Color=FF0000}] \RenewDocumentCommand{\MacroLongFont}{} { \mysourcecodeprolight\small } % The character of visible space is now taken from Latin Modern Mono % to prevent fonts in T1. The original definition for xetex/luatex is % \def\verbvisiblespace{\usefont{OT1}{cmtt}{m}{n}\asciispace} \def\verbvisiblespace{{\fontfamily{lmtt}\selectfont\char"2423}} \usepackage{unicode-math} \setmathfont[Scale = 0.95]{latinmodern-math.otf} \usepackage{fontawesome5} \newfontfamily\fetamontotf{ffmw10.otf}[ Scale = 0.95,% RawFeature = {+latn,+rand,+kern,+size},% FontFace = {b}{n}{ffmw10.otf},% fix replace font ] \usepackage[svgnames]{xcolor} \usepackage[sf,bf,compact,medium,pagestyles]{titlesec} \usepackage{lastpage,microtype,attachfile2} \usepackage{adjustbox,multicol,listings,accsupp,titletoc} \usepackage{imakeidx,tikz,enumext} % main \usepackage{scontents} \usepackage{shellesc} \usepackage[contents]{colordoc} % \show\docCodelineNo \def\textnew#1{\color{color-def}#1\/} \def\AltMacroFont{\fontencoding\encodingdefault \fontfamily\ttdefault \fontseries\mddefault \fontshape\updefault \small }% % Patching colordoc.sty to work with l3doc.cls \ExplSyntaxOn \cs_new_eq:cN { liii@xmacro@code } \__codedoc_xmacro_code:n \ExplSyntaxOff \begingroup \makeatletter \catcode`\[\@ne\catcode`\]\tw@ \@makebracesactive \gdef{[\@openingbrace[\char'173]] \gdef}[\@closingbrace[\char'175]] \catcode`\|\z@\catcode`\%12 \catcode`\ \active\catcode`\\\active |gdef|xmacro@code#1% \end{macrocode}[|liii@xmacro@code[#1]|end[macrocode]] |catcode`| 12|gdef|sxmacro@code#1% \end{macrocode*}[|liii@xmacro@code[#1]|end[macrocode*]] |endgroup % Patching colordoc.sty to work with doc v3 (TeX Live 2023 & lualatex-dev) \usepackage{etoolbox} \makeatletter \@ifpackagelater{doc}{2022-06-01}% {\patchcmd\macro@finish {\ifnot@excluded % \if \edef\@tempa{\noexpand\SpecialIndex{\bslash\macro@namepart}}% \@tempa \fi}% {\maybe@index@macro \macro@namepart} {}{\FAILED}% \let\default@color\current@color }% {} \makeatother \EnableCrossrefs % \PageIndex, \CodelineIndex undoes what \PageIndex does % \CodelineIndex tries to open another write stream for the index file. We don't % want that, so we temporarily make \makeindex a no-op: \let\ORGmakeindex\makeindex \def\makeindex{} \CodelineIndex \let\makeindex\ORGmakeindex \DoNotIndex{\ , \1,\^} \expandafter\DoNotIndex\expandafter{\string\{} \expandafter\DoNotIndex\expandafter{\string\}} \expandafter\DoNotIndex\expandafter{\string\begin} \newcommand{\HP}[1]{\emph{\hyperpage{#1}}\normalsize} \ExplSyntaxOn \cs_new_protected:Npn \StartImplementation { \bool_set_true:N \l__codedoc_in_implementation_bool } \bool_set_false:N \l__codedoc_in_implementation_bool \cs_new_protected:Npn \MYSortIndex #1 #2 { \bool_if:NTF \l__codedoc_in_implementation_bool { \index{#1\actualchar#2|HP} } { \index[userdoc]{#1\actualchar#2|HP} } } \ExplSyntaxOff % imakeidx config \indexsetup{level=\section,firstpagestyle=myheader,othercode=\pagestyle{myheader}} \makeindex[name=userdoc,options={-q -s gind.ist},columnsep=15pt,title={Index of Documentation}] \makeindex[options={-q -s gind.ist},columnsep=15pt,title={Index of Implementation}] % Now, after imakeidx opens the write stream for the index file, we copy % the reference to \@indexfile: \makeatletter \expandafter\let\expandafter\@indexfile\csname \jobname @idxfile\endcsname \makeatother % Set \parindent \setlength{\parindent}{0pt} % Colors \definecolor{optcolor}{rgb}{0.281,0.275,0.485} \definecolor{pkgcolor}{rgb}{0,0.5,0.5} \definecolor{araracolor}{rgb}{0, 0.72, 0.28} \definecolor{linkcolor}{rgb}{0.04,0.38,0.04} \definecolor{rulecolor}{rgb}{0.96,0.96,0.96} % Only for arara... I like arara :) \usepackage[scale=0.85]{comfortaa} \newcommand{\araratext}[1]{{\small\normalfont\comfortaa\color{araracolor}\bfseries#1}} \newcommand*\arara{\araratext{ar\kern-.03emar\kern-.03ema}} % User level commands \ExplSyntaxOn % Logo \NewDocumentCommand{\pkglogo}{} { \group_begin: \LibertinusSansOsF{\textcolor{pkgcolor}{enum}\textcolor{OrangeRed}{ext}} \group_end: } % Custom \meta[...]{...}, \marg[...]{...} and \oarg[...]{...} with color \NewDocumentCommand{\mymeta}{O{}m} { \userdoc_meta_generic:Nnn \userdoc_meta:n { #1 } { #2 } } \NewDocumentCommand{\mymarg}{O{}m} { \userdoc_meta_generic:Nnn \userdoc_marg:n { #1 } { #2 } } \NewDocumentCommand{\myoarg}{O{}m} { \userdoc_meta_generic:Nnn \userdoc_oarg:n { #1 } { #2 } } \NewDocumentCommand{\myparg}{O{}m} { \userdoc_meta_generic:Nnn \userdoc_parg:n { #1 } { #2 } } % Variables and keys \tl_new:N \l_userdoc_meta_font_tl \keys_define:nn { userdoc / mymeta } { type .choice:, type / tt .code:n = \tl_set:Nn \l_userdoc_meta_font_tl { \ttfamily }, type / rm .code:n = \tl_set:Nn \l_userdoc_meta_font_tl { \rmfamily }, type .initial:n = tt, cf .tl_set:N = \l_userdoc_meta_color_tl, cf .initial:n = optcolor, ac .tl_set:N = \l_userdoc_meta_anglecolor_tl, ac .initial:n = lightgray, sbc .tl_set:N = \l_userdoc_meta_brackcolor_tl, sbc .initial:n = gray, cbc .tl_set:N = \l_userdoc_meta_bracecolor_tl, cbc .initial:n = gray, pbc .tl_set:N = \l_userdoc_meta_parencolor_tl, pbc .initial:n = gray, } % Internal commands \cs_new_protected:Npn \userdoc_meta_generic:Nnn #1 #2 #3 { \group_begin: \keys_set:nn { userdoc / mymeta } { #2 } \color{ \l_userdoc_meta_color_tl } \l_userdoc_meta_font_tl #1 { #3 } % #1 is \userdoc_meta:n, \userdoc_marg:n or \userdoc_oarg:n \group_end: } \cs_new_protected:Npn \userdoc_meta:n #1 { \userdoc_meta_angle:n { \textlangle } \userdoc_meta_meta:n { #1 } \userdoc_meta_angle:n { \textrangle } } \cs_new_protected:Npn \userdoc_marg:n #1 { \userdoc_meta_brace:n { \textbraceleft } \userdoc_meta:n { #1 } \userdoc_meta_brace:n { \textbraceright } } \cs_new_protected:Npn \userdoc_oarg:n #1 { \userdoc_meta_brack:n { [ } \userdoc_meta:n { #1 } \userdoc_meta_brack:n { ] } } \cs_new_protected:Npn \userdoc_parg:n #1 { \userdoc_meta_brace:n { ( } \userdoc_meta:n { #1 } \userdoc_meta_brace:n { ) } } \cs_new_protected:Npn \userdoc_meta_meta:n #1 { \textnormal{\textit{#1}} } \cs_new_protected:Npn \userdoc_meta_angle:n #1 { \group_begin: \fontfamily{lmr}\selectfont \textcolor{\l_userdoc_meta_anglecolor_tl}{#1} \group_end: } \cs_new_protected:Npn \userdoc_meta_brace:n #1 { \group_begin: \color{\l_userdoc_meta_bracecolor_tl} #1 \group_end: } \cs_new_protected:Npn \userdoc_meta_brack:n #1 { \textcolor{\l_userdoc_meta_brackcolor_tl}{#1} } % \envexamp{m} \newsavebox{\boxexaenv} \tl_new:N \l_tempc_tl \NewDocumentCommand \envexamp { m } { \tl_set:Nn \l_tempc_tl { #1 } \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tempc_tl \begin{lrbox}{\boxexaenv}% \begin{minipage}[t]{3\marginparwidth}% \raggedright\ttfamily\small \textcolor{gray}{\textbackslash begin\{\textcolor{pkgcolor}{{\tl_use:N \l_tempc_tl}}\}\myoarg [type=tt,sbc=gray,ac=lightgray,cf=optcolor]{keyval ~ list}}\par% \hspace{0.25cm}\ics*{item}\space\mymeta[ac=lightgray,cf=gray]{item ~ content}\par% \hspace{0.25cm}\ics*{item}\space\myoarg[sbc=gray,ac=lightgray,cf=optcolor]{custom}\space\mymeta[ac=lightgray,cf=gray]{item ~ content}\par \hspace{0.25cm}\ics*{item*}\myoarg[sbc=gray,ac=lightgray,cf=optcolor]{symbol}\myoarg[sbc=gray,ac=lightgray,cf=optcolor]{offset}\space\mymeta[ac=lightgray,cf=gray]{item ~ content}\par \textcolor{gray}{\textbackslash end\{{\textcolor{pkgcolor}{{\tl_use:N \l_tempc_tl}}}\}}\par \end{minipage}% \end{lrbox}% \usebox{\boxexaenv} } % \cmdexamp{o m o m o} \tl_new:N \l_tempd_tl \NewDocumentCommand \cmdexamp { o m o m o } { \group_begin: \small\ttfamily \textcolor{pkgcolor}{\textbackslash#2} \IfValueT{#1}{ \textcolor{MediumOrchid}{#1} } \IfValueT{#3} { % \textnormal{\ttfamily } or \c{texttt}\cB\{ \cE\} \tl_set:Nn \l_tempd_tl { #3 } % \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tempd_tl \regex_replace_once:nnN { (\*) } { \c{texttt}\cB\{\c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} \cE\} } \l_tempd_tl \myoarg[type=tt,sbc=gray,ac=lightgray,cf=optcolor]{\tl_use:N \l_tempd_tl} } \IfValueTF{#5} { \mymeta[ac=gray,type=tt,cf=MediumOrchid]{#5}% \mymeta[type=tt,ac=gray,cf=optcolor]{#4} \mymeta[ac=gray,type=tt,cf=MediumOrchid]{#5}% } { \mymarg[type=tt,cbc=gray,ac=lightgray,cf=optcolor]{#4} } \par \group_end: } % \keyexamp{s m m m} \NewDocumentCommand \keyexamp{s m m m } { \adjustbox{outer=-\marginparsep}{\textcolor{optcolor}{\small\ttfamily{#2}}} \IfBooleanTF{#1} { \hphantom{\textcolor{white}{\,\bfseries\texttt{=}}\,{}} \mymeta[type=tt,cbc=gray,ac=lightgray,cf=lightgray]{\small{#3}} } { \textcolor{gray}{\,\bfseries\texttt{=}}\,{} \mymarg[type=tt,cbc=gray,ac=lightgray,cf=optcolor]{\small{#3}} } \hfill\textcolor{gray}{\small\textsf{default}:~\emph{#4}}\par% \MYSortIndex{Keys}{Keys ~ for ~ environments ~ provide ~ by ~ \pkglogo :>\texttt{#2}} } % \keyexampcmd{s m m m o} \NewDocumentCommand \keyexampcmd{s m m m o} { \adjustbox{outer=-\marginparsep}{\textcolor{optcolor}{\small\ttfamily{#2}}} \IfBooleanTF{#1} { \hphantom{\textcolor{white}{\,\bfseries\texttt{=}}\,{}} \mymeta[type=tt,cbc=gray,ac=lightgray,cf=lightgray]{\small{#3}} } { \textcolor{gray}{\,\bfseries\texttt{=}}\,{} \mymarg[type=tt,cbc=gray,ac=lightgray,cf=optcolor]{\small{#3}} } \hfill\textcolor{gray}{\small\textsf{default}:~\emph{#4}}\par% \IfValueTF{#5} { \MYSortIndex{Keys}{Keys ~ for ~ \texttt{\textbackslash{}#5} ~ provide ~ by ~ \pkglogo :>\texttt{#2}} } { \MYSortIndex{Keys}{Keys ~ for ~ \texttt{\textbackslash{}anskey} ~ provide ~ by ~ \pkglogo :>\texttt{#2}} \MYSortIndex{Keys}{Keys ~ for ~ \texttt{anskey\textcolor{MediumOrchid}{*}} ~ provide ~ by ~ \pkglogo :>\texttt{#2}} } } % \keyexampenv{s m m m} \NewDocumentCommand \keyexampenv{s m m m } { \adjustbox{outer=-\marginparsep}{\textcolor{optcolor}{\small\ttfamily{#2}}} \IfBooleanTF{#1} { \hphantom{\textcolor{white}{\,\bfseries\texttt{=}}\,{}} \mymeta[type=tt,cbc=gray,ac=lightgray,cf=lightgray]{\small{#3}} } { \textcolor{gray}{\,\bfseries\texttt{=}}\,{} \mymarg[type=tt,cbc=gray,ac=lightgray,cf=optcolor]{\small{#3}} } \hfill\textcolor{gray}{\small\textsf{default}:~\emph{#4}}\par% \MYSortIndex{Keys}{Keys ~ for ~ \texttt{anskey\textcolor{MediumOrchid}{*}} ~ provide ~ by ~ \pkglogo :>\texttt{#2}} } % \mykey{m} \NewDocumentCommand \mykey{ m } { \tl_set:Nn \l_tmpa_tl { #1 } \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \textcolor{optcolor}{\ttfamily \tl_use:N \l_tmpa_tl } %\textcolor{optcolor}{\texttt{#1}} \MYSortIndex{Keys}{Keys ~ for ~ environments ~ provide ~ by ~ \pkglogo :>\texttt{\tl_use:N \l_tmpa_tl}} } % \mykeycmd{o s m} \NewDocumentCommand \mykeycmd{ o s m } { \tl_set:Nn \l_tmpa_tl { #3 } \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \textcolor{optcolor}{\ttfamily \tl_use:N \l_tmpa_tl } %\textcolor{optcolor}{\texttt{#1}} \IfBooleanTF{#2} { \MYSortIndex{Keys}{Keys ~ for ~ \texttt{anskey\textcolor{MediumOrchid}{*}} ~ provide ~ by ~ \pkglogo :>\texttt{\tl_use:N \l_tmpa_tl}} } { \IfValueTF{#1} { \MYSortIndex{Keys}{Keys ~ for ~ \texttt{\textbackslash{}#1} ~ provide ~ by ~ \pkglogo :>\texttt{\tl_use:N \l_tmpa_tl}} } { \MYSortIndex{Keys}{Keys ~ for ~ \texttt{\textbackslash{}anskey} ~ provide ~ by ~ \pkglogo :>\texttt{\tl_use:N \l_tmpa_tl}} \MYSortIndex{Keys}{Keys ~ for ~ \texttt{anskey\textcolor{MediumOrchid}{*}} ~ provide ~ by ~ \pkglogo :>\texttt{\tl_use:N \l_tmpa_tl}} } } } % \mypkg{sm} \NewDocumentCommand \mypkg { s m } { \group_begin: \IfBooleanTF{#1} { \pkglogo \MYSortIndex{packages}{Packages :>\texttt{#2}} } { \textcolor{OrangeRed}{\texttt{#2}}% \MYSortIndex{packages}{Packages :>\texttt{#2}}% } \group_end: } % \myclass{m} \NewDocumentCommand \myclass { m } { \mbox{\texttt{\textcolor{OrangeRed}{#1}}} \MYSortIndex{class}{Document ~ class :>\texttt{#1}} } % \myenv{sm} \NewDocumentCommand \myenv { s m O{}} { \IfBooleanTF{#1} { \tl_set:Nn \l_tmpa_tl { #2 } \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \textcolor{pkgcolor}{\ttfamily{\tl_use:N \l_tmpa_tl}}% \MYSortIndex{environment}{Environments ~ provide ~ by ~\pkglogo :>\texttt{\tl_use:N \l_tmpa_tl}} } { \textcolor{SlateBlue}{\ttfamily{#2}}% \MYSortIndex{environment}{Environments :>\texttt{#2}} } } % \ics{sm} \NewDocumentCommand \ics {s m} { \IfBooleanTF{#1} { \tl_set:Nn \l_tmpa_tl { #2 } \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \regex_replace_once:nnN { (!) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \textcolor{pkgcolor}{\ttfamily\textbackslash{\tl_use:N \l_tmpa_tl}} \MYSortIndex{Commands}{Commands ~ provide ~ by ~ \pkglogo :>\texttt{\textbackslash#2}} } { \textcolor{blue!75}{\ttfamily\textbackslash{#2}} \MYSortIndex{#2}{\texttt{\textbackslash#2}} } } % \icounter{m} \NewDocumentCommand \icounter { m } { \textcolor{optcolor}{\ttfamily #1} \MYSortIndex{Counters}{Counters ~ defined ~ by ~ \pkglogo :>\texttt{#1}} } % \ilabel{sm} \NewDocumentCommand \ilabel {s m } { \tl_set:Nn \l_tmpb_tl { #2 } \tl_remove_once:Nn \l_tmpb_tl { . } \tl_remove_once:Nn \l_tmpb_tl { ) } \tl_remove_once:Nn \l_tmpb_tl { ( } \MYSortIndex{Labels}{ Labels ~ provide ~ by ~ \pkglogo :>\texttt{\textbackslash \tl_use:N \l_tmpb_tl }} \tl_set:Nn \l_tmpa_tl { #2 } \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \regex_replace_once:nnN { (\.) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \regex_replace_once:nnN { (\() } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \regex_replace_once:nnN { (\)) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \tl_put_left:Nn \l_tmpa_tl { \textbackslash } \IfBooleanT{#1} { \tl_put_left:Nn \l_tmpa_tl { \textcolor{MediumOrchid}{ ( } } }% \textcolor{optcolor}{ \ttfamily \tl_use:N \l_tmpa_tl } } % \mydim{m} \NewDocumentCommand \mydim { m } { \tl_set:Nn \l_tmpa_tl { #1 } \regex_replace_all:nnN { (\d) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \regex_replace_all:nnN { (\.) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \textcolor{gray}{ \ttfamily \tl_use:N \l_tmpa_tl } } % \myfile{m} \NewDocumentCommand \myfile { m } { \group_begin: \tl_clear:N \l_tmpa_tl \tl_set:Nn \l_tmpa_tl { #1 } \regex_replace_all:nnN { (\d) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \regex_replace_all:nnN { (\.) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \textcolor{gray}{ \ttfamily \tl_use:N \l_tmpa_tl } \group_end: } % \myvarenv{m} \NewDocumentCommand \myvarenv { s m } { \group_begin: \tl_set:Nn \l_tmpa_tl { #2 } \regex_replace_once:nnN { @{2} }{ enumext } \l_tmpa_tl \regex_replace_once:nnN { (\*) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \regex_replace_once:nnN { (\:) } { \c{textcolor}\cB\{MediumOrchid\cE\}\cB\{\1\cE\} } \l_tmpa_tl \IfBooleanTF{#1} { \textcolor{pkgcolor}{ \ttfamily \tl_use:N \l_tmpa_tl } } { \tl_put_left:Nn \l_tmpa_tl { \textbackslash } \textcolor{gray}{ \ttfamily \tl_use:N \l_tmpa_tl } } \group_end: } % \aviso \NewDocumentCommand \aviso { } { \par\hspace*{-0.5\marginparsep}% \makebox[0pt][r] { \makebox[\marginparsep][r] { \scriptsize\textcolor{pkgcolor}{\reflectbox{\faIcon{tag}}}% tagged PDF } } \hskip 0.5\marginparsep } % \bomba \NewDocumentCommand \bomba { } { \par\hspace*{-0.5\marginparsep}% \makebox[0pt][r] { \makebox[\marginparsep][r] { \footnotesize\textcolor{pkgcolor}{\faIcon{bomb}} } } \hskip 0.5\marginparsep } \NewDocumentEnvironment{important}{ s } { \small\sffamily \IfBooleanTF{#1} { \bomba% } { \aviso } }{} \ExplSyntaxOff % email https://tex.stackexchange.com/a/663 \catcode`\_=11\relax% \newcommand\email[1]{\_email #1\q_nil}% \def\_email#1@#2\q_nil{% \href{mailto:#1@#2}{{\emailfont #1\emailampersat #2}}% }% \newcommand\emailfont{\sffamily}% \newcommand\emailampersat{{\color{optcolor}\footnotesize @}}% \catcode`\_=8\relax% % Don't copy numbers in code example \newcommand*{\noaccsupp}[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} % Create a language for documentation \lstdefinelanguage{enumext-doc}{ texcsstyle = *,% escapechar =`,% extendedchars = true,% keepspaces = true,% stringstyle = {\color{red}},% basicstyle = \ttfamily,% \small alsoletter = {-,.},% @, % comments morecomment = [l]{\%},% commentstyle = \ttfamily\small\color{lightgray},% % Important words 1 keywordstyle = [1]{\color{gray}},% keywords = [1]{begin,end,Verbatim,env,myseq,false,NewDocumentCommand,newlength, the, red, blue, gray,% settowidth, dimeval, dimexpr, IfBooleanTF,footnotehyper, DocumentMetadata, % IfDocumentMetadataTF, RenewDocumentCommand, pt, em, SuspendTagging, ResumeTagging,% },% % Other words 2 keywordstyle = [2]{\color{blue!75}},% keywords = [2]{usepackage,section,documentclass,input,listparindent,linewidth, emph, textbf,makesavenoteenv, makelabel,% columnseprule, footnote, footnotemark, footnotetext, raggedcolumns, hspace, parindent, removelastskip, % subsection, list,endlist,leftmargin, itemindent,bfseries,endminipage, minipage, parskip, raisebox, strut,smash, % , labelwidth,labelsep,labelindent,label,ref,topsep,parsep,includegraphics, itemize, description, NewCommandCopy, % multicolsep,leftmargini,leftmarginii, hfill, small, vspace, par, parbox, value, noindent, makebox, textcolor, % itemindent, labelwidth, leftmarginiii,leftmarginiv,itemindent, itemsep, strutbox, raggedright, cs_new_eq, N, NN,% labelwidth, fbox, addvspace, Alph, alph, arabic, Roman, roman, partopsep, baselineskip, mode_leave_vertical,% textbullet, textendash, textasteriskcentered, textperiodcentered, raggedleft, peek_remove_spaces, skip_horizontal, % triangleright, diamond, circ, parleft, star, centering, ast, hyperlink,hypertarget,IfHyperBoolean,newtheorem, % aux_i, aux_ii, aux_iii, w, n, N, if@noitemarg, if, if@hyper@item, hyper, noitemarg, skip_vertical, },% % Other words 3 keywordstyle = [3]{\color{optcolor!85}},% keywords = [3]{document,article,setlength,pagestyle,definecolor, chapter,},%, % Reserved words 4 (enumext pkg) keywordstyle = [4]{\color{pkgcolor}},% keywords = [4]{enumext,keyans,keyanspic, getkeyans, anskey, anspic, item, anskey*, itemwidth, enumextmeta, % setenumext,printkeyans,miniright,labelbx, mywrap, descitemwd,theenumXi,theenumXii,theenumXiii,% setenumextmeta, foreachkeyans, theenumXiv,theenumXv, theenumXvii, theenumXviii},% % Reserved words 5 (plain TeX or internal) keywordstyle = [5]{\color{red}},% keywords = [5]{makeatletter,makeatother,let,verb,def,prevdepth,glue, if@minipage,% if@noitemarg splittopskip,showboxdepth,topskip,showoutput,nointerlineskip, ignorespaces, unskip, unkern, lastnodetype,% rightskip, @rightskip, @flushglue, hbadness, hss},% % Reserved words 6 (optcolor) KEYS keywordstyle = [6]{\color{optcolor}},% keywords = [6]{save-ans,wrap-ans,save-ref,show-pos,show-ans,columns,list-offset, eunumXi,% nosep,before,after,start, right, item-sym, item-sep, hyperfootnotes, item-star, % scale,wrap-label,font,first,widest,mini-env,list-indent, no-store, save-key,% store-env, print-env, write-out, force-eol, write-env, overwrite, unknown, % midsep, wrapper,label-pos,label-sep, layout-sty, layout-sep, layout-top, lang,% pdfversion, pdfstandard, testphase, alt},% % Reserved words 7 (label values) keywordstyle = [7]{\color{MediumOrchid}},% keywords = [7]{m,s,M,VIII,viii,v,E,t,l,A,XXIII,true, false,test,sample,above,below,ua-2,phase-III,% en-US, math, title, table, firstaid },% % literate literate =*{\{}{{{\color{gray}{\char`\{}}}}{1} {\}}{{{\color{gray}{\char`\}}}}}{1} {\|}{{{\color{gray}{\char`\|}}}}{1} {\$}{{{\color{gray}{\char`\$}}}}{1} {\#}{{{\color{optcolor}{\char`\#}}}}{1} {[}{{\textcolor{gray}{[}}}{1} {]}{{\textcolor{gray}{]}}}{1} {,}{{\textcolor{gray}{,}}}{1} {;}{{\textcolor{gray}{;}}}{1} {:}{{\textcolor{red}{:}}}{1} {`}{{\textcolor{gray}{\textasciigrave}}}{1} {\&}{{\textcolor{gray}{\&}}}{1} {>}{{\textcolor{OrangeRed}{\guillemotright}}}{1} {<}{{\textcolor{OrangeRed}{\guillemotleft}}}{1} {*}{{\textcolor{MediumOrchid}{*}}}{1} {!}{{\textcolor{MediumOrchid}{!}}}{1} {@}{{\textcolor{MediumOrchid}{@}}}{1}% {\^}{{\textcolor{optcolor}{\textasciicircum}}}{1} {0}{{\textcolor{MediumOrchid}{0}}}{1} {1}{{\textcolor{MediumOrchid}{1}}}{1} {2}{{\textcolor{MediumOrchid}{2}}}{1} {3}{{\textcolor{MediumOrchid}{3}}}{1} {4}{{\textcolor{MediumOrchid}{4}}}{1} {5}{{\textcolor{MediumOrchid}{5}}}{1} {6}{{\textcolor{MediumOrchid}{6}}}{1} {7}{{\textcolor{MediumOrchid}{7}}}{1} {8}{{\textcolor{MediumOrchid}{8}}}{1} {9}{{\textcolor{MediumOrchid}{9}}}{1} {.0}{{\textcolor{MediumOrchid}{.0}}}{2}% Following is to ensure that only periods {.1}{{\textcolor{MediumOrchid}{.1}}}{2}% followed by a digit are changed. {.2}{{\textcolor{MediumOrchid}{.2}}}{2} {.3}{{\textcolor{MediumOrchid}{.3}}}{2} {.4}{{\textcolor{MediumOrchid}{.4}}}{2} {.5}{{\textcolor{MediumOrchid}{.5}}}{2} {.6}{{\textcolor{MediumOrchid}{.6}}}{2} {.7}{{\textcolor{MediumOrchid}{.7}}}{2} {.8}{{\textcolor{MediumOrchid}{.8}}}{2} {.9}{{\textcolor{MediumOrchid}{.9}}}{2} {=}{{\textcolor{gray}{=}}}{1},% }[keywords,tex,comments,strings]% end language % \begin{examplecode}[key=val]...\end{examplecode} \lstnewenvironment{examplecode}[1][]{% \lstset{ language = enumext-doc,% stringstyle = {\color{red}},% basicstyle = \ttfamily\small,% columns = fullflexible,% fontadjust = true,% aboveskip = 8pt,% belowskip = 5pt,% rulecolor = \color{gray!50},% framesep = \fboxsep,% framerule = \fboxrule,% xleftmargin = \dimexpr\fboxsep+\fboxrule\relax,% xrightmargin= \dimexpr\fboxsep+\fboxrule\relax,% #1,% }% close lstset }{\vspace{-\parskip}}% close examplecode % \lstinline[style=inline]|...| \lstdefinestyle{inline} { language = enumext-doc,% upquote = true,% numbersep = 1em,% escapechar =`,% basicstyle =\ttfamily,%\small numberstyle = \tiny\color{lightgray}\noaccsupp,% literate =*{\%}{{\textcolor{gray}{\%}}}{1} {i}{{\textcolor{optcolor}{i}}}{1} {ii}{{\textcolor{optcolor}{ii}}}{2} {iii}{{\textcolor{optcolor}{iii}}}{3} {iv}{{\textcolor{optcolor}{iv}}}{2} {v}{{\textcolor{optcolor}{v}}}{1} {vi}{{\textcolor{optcolor}{vi}}}{1} } % Set default \lstinline style \lstset{style=inline} % Get file info \GetFileInfo{enumext.sty} % Config hyperref \hypersetup { allcolors = linkcolor, colorlinks = true, linktoc = all, pdftitle = {.:: The enumext package --- \fileinfo{} ::.}, pdfauthor = {Pablo González L}, pdfsubject = {Documentation for \fileversion{} [\filedate] }, pdfkeywords = {worksheets, multiple choice, expl3, l3prop, l3seq, list, enumerate, store answers, tagged}, bookmarksopenlevel = 2, } % Configuration titleps and titlesec \settitlemarks{section} \renewpagestyle{plain}[\color{optcolor}\small\sffamily]{% \setfoot{\rlap{\hskip\dimexpr-\oddsidemargin-1in\relax% \parbox{1.93\paperwidth}{\hfil\thepage\,/\,\pageref{LastPage}}}}% {}% {}% } \newpagestyle{myheader}[\color{optcolor}\small\sffamily]{% \renewcommand\makeheadrule{% \rlap{\hskip\dimexpr-\oddsidemargin-1in\relax \color{rulecolor}\rule[0.3cm]{\paperwidth}{0.7cm}}\hss } \setfoot{\rlap{\hskip\dimexpr-\oddsidemargin-1in\relax% \parbox{1.93\paperwidth}{\hfil\thepage\,/\,\pageref{LastPage}}}}% {\parbox{\textwidth}{\raggedright \textcolor{gray}{\raisebox{-1pt}{\textcopyright}{}2024 by Pablo González L}}}% {}% \sethead{\llap{\raisebox{0.55cm}{\parbox{\dimexpr\oddsidemargin+1in\relax}{\makebox[0pt][l]{\hspace{15pt}\pkglogo\space\fileversion}}}}} {\raisebox{0.55cm}{\parbox{\textwidth}{\hspace*{-\oddsidemargin}\centering\small\S.\thesection\space\sectiontitle}}}% {}% } \titlecontents{section}[0mm]{}% {\bfseries\contentspush{\makebox[5mm][l]{\thecontentslabel\hfill}}}% {\hspace*{-5mm}}% numberless {\hspace{0.25em}\titlerule*[6pt]{.}\contentspage}% \titlecontents{subsection}[5mm]{}% {\contentspush{\makebox[6mm][l]{\thecontentslabel\hfill}}} {\hspace*{-11mm}}% numberless {\hspace{0.25em}\titlerule*[6pt]{.}\contentspage}% \titlecontents{subsubsection}[11mm]{}% {\contentspush{\makebox[8mm][l]{\thecontentslabel\hfill}}} {\hspace*{-19mm}}% numberless {\hspace{0.25em}\titlerule*[6pt]{.}\contentspage}% % Table of contents \makeatletter \renewcommand\tableofcontents{% \begingroup% \section*{\contentsname\quad{\color{gray}\leaders\hrule height 5pt depth -4.4pt\hfill}% \@mkboth{% \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}% \vspace*{-14pt} \setlength{\columnsep}{10pt}% \begin{multicols}{2}% \@starttoc{toc}% \end{multicols}% \vspace*{-3pt}{\color{gray}\hrule height 0.6pt}% \vspace*{5pt} \endgroup } \makeatother % \thanks \makeatletter \renewcommand*{\@fnsymbol}[1]{\ensuremath{\ifcase#1\or \textcolor{pkgcolor}{*} \or \textcolor{pkgcolor}{\dagger} \or \ddagger\or \mathsection \or \mathparagraph\or \|\or **\or \dagger\dagger \or \ddagger\ddagger \else\@ctrerr\fi}} \makeatother % \usepackage{lua-visual-debug} \usepackage[font=small,skip=2pt]{caption} % For input samples \usepackage{tikzducks,siunitx,amssymb} \sisetup{output-decimal-marker={,}} \newcommand*{\myCircled}[1]{% \begin{tikzpicture}[baseline=(number.base)] \node[circle, draw=green!10!gray, inner sep=1pt, fill=blue!30!green!10] (number) {#1}; \end{tikzpicture}% } \usetikzlibrary{shapes.geometric} \newcommand*{\mySquared}[1]{% \begin{tikzpicture}[baseline=(number.base),square/.style={regular polygon,regular polygon sides=4}] \node[square, rounded corners=1pt, inner sep=1pt, draw=none, fill=gray!40] (number) {\makebox[\height]{#1}}; \end{tikzpicture}% } % For SAT sample \newsavebox{\satbox} \sbox\satbox{\small\textbf{67}}% \NewDocumentCommand \stylesat { m } {% \setlength{\fboxsep}{2pt}% \raisebox{2\fboxsep}{% \noindent\colorbox{black}{\textcolor{white}{\makebox[\dimeval{\labelwidth-2\fboxsep}][c]{\small\textbf{\vphantom{67}#1}}}}% \colorbox{lightgray}{\phantom{\rule[-\dp\satbox]{\dimeval{\linewidth-2\fboxsep}}{\dimeval{\dp\satbox+\ht\satbox}}}}}% } % For non-numbered list samples, need ´%´ at end (prevent wrong unwanted spaces) \NewDocumentCommand \labelbx { s +m } {% \IfBooleanTF{#1} {\strut\smash{\parbox[t]{\labelwidth}{\raggedright{#2}}}}% {\strut\smash{\parbox[t]{\labelwidth}{\raggedleft{#2}}}}% } %%%\ExplSyntaxOn %%5\NewDocumentCommand \labelbx { s +m } %% { %% %% \tag_suspend:n {\parbox} %% \IfBooleanTF{#1} %% { \parbox[t]{\labelwidth}{\raggedright{#2}} } %% { \parbox[t]{\labelwidth}{\raggedleft{#2}} } %% %% \tag_resume:n {\parbox} %% } %%%\ExplSyntaxOff \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{ % \scalebox{2.67}{\pkglogo}\\[-10pt] % {\large\textcolor{gray}{\fetamontotf{enumerate exercise sheets}}}\\[0pt] % \fileversion \quad \filedate\thanks{ % This file describes a documentation for \fileversion, last revised % \filedate.}\\[25pt] % \author{ % \large % \raisebox{-1pt}{\textcopyright}{}2024 by Pablo González\thanks{ % E-mail: \textcolor{OrangeRed}{\textsf{\guillemotleft}}\email{pablgonz@educarchile.cl}\textcolor{OrangeRed}{\textsf{\guillemotright}}. % }% % } % \small % \textsc{ctan}: \url{https://www.ctan.org/pkg/enumext}\\ % \textcolor{gray}{\scriptsize\faIcon[regular]{github}}\,\,\,\url{https://github.com/pablgonz/enumext} % \vspace*{-2cm} % } % \date{} % \maketitle % % \begin{abstract} % This package provides enumerated list environments compatible % with \emph{tagging} \texttt{PDF} for creating \emph{\enquote{simple % exercise sheets}} along with \emph{\enquote{multiple choice questions}}, % storing the \emph{\enquote{answers}} to these in memory using \mypkg{multicol} % and \mypkg{scontents} packages. % \end{abstract} % % \tableofcontents % % \section*{Motivation and acknowledgments} % % Usually it is enough to use the classic \myenv{enumerate} environment to % generate \emph{\enquote{simple exercise sheets}} or % \emph{\enquote{multiple choice questions}}, the basic idea behind % \mypkg*{enumext} is to cover three points: % % \begin{enumerate}[left=0pt, nosep,labelsep=5pt, label=\small\arabic*.,topsep=2pt] % \item To have a simple interface to be able to write \emph{\enquote{lists of % exercises}} with \emph{\enquote{answers}}. % \item To have a simple interface for writing \emph{\enquote{multiple choice % questions}}. % \item To have a simple interface for placing \emph{\enquote{columns}} % and \emph{\enquote{drawings}} or \emph{\enquote{tables}}. % \end{enumerate} % % This package would not be possible without Phelype Oleinik who has % collaborated and adapted a large part of the code and all % \hologo{LaTeX} team for their great work and to the different members % of the \href{https://tex.stackexchange.com}{TeX-SX} community who have % provided great answers and ideas. Here a note of the main ones: % % \begin{enumerate}[left=0pt, labelsep=5pt, nosep, label=\small\arabic*.,topsep=2pt] % \item Answer given by Alan Munn in \href{https://tex.stackexchange.com/a/300418}{\textbackslash topsep, \textbackslash itemsep, \textbackslash partopsep, \textbackslash parsep - what do they each mean (and what about the bottom)?} % % \item Answer given by Enrico Gregorio in \href{https://tex.stackexchange.com/a/34172}{Understanding minipages - aligning at top} % % \item Answer given by Ulrich Diez in \href{https://tex.stackexchange.com/a/553839/7832}{Different mechanics of hyperlink vs. hyperref} % % \item Answer given by Enrico Gregorio in \href{https://tex.stackexchange.com/a/294460/7832}{Minipage and multicols, vertical alignment} % % \end{enumerate} % % \thispagestyle{plain} % % \section*{License and Requirements} % \label{sec:licence} % % Permission is granted to copy, distribute and/or modify this software under % the terms of the LaTeX Project Public License (lppl), version 1.3 or later % (\url{https://www.latex-project.org/lppl.txt}). % The software has the status \enquote{maintained}. % % The \mypkg*{enumext} package loads and requires \mypkg{multicol}\cite{multicol} % and \mypkg{scontents}\cite{scontents} packages, need to have a modern \hologo{TeX} distribution such as % \hologo{TeX} Live or \hologo{MiKTeX}. It has been tested with the standard % classes provided by \hologo{LaTeX}: \myclass{book}, \myclass{report}, % \myclass{article} and \myclass{letter} on \mydim{10pt}, \mydim{11pt} and \mydim{12pt}. % % \smallskip % % \begin{important}* % The minimum requirement is \hologo{LaTeX} release 2024-11-01. % \end{important} % % \pagestyle{myheader} % % \section{Introduction} % % In the \hologo{LaTeX} world world there are many useful packages and % classes for creating \emph{\enquote{lists of exercises}}, \emph{\enquote{worksheets}} or % \emph{\enquote{multiple choice questions}}, classes like \myclass{exam}\cite{exam} % and packages like \mypkg{xsim}\cite{xsim} do the job perfectly, but % they don't always fit the basic day to day needs. % % \smallskip % % In my work (and in the work of many teachers) it is common to use % \emph{\enquote{simple exercise sheets}} also known as % \emph{\enquote{informal lists of exercises}}, as an example: % % \smallskip % % \begin{enumext}[save-ans=temp2,columns=2,nosep,save-ref=true]% % \item Factor $x^{2}-2x+1$ \anskey{$\left(x-1\right)^{2}$} % \item Factor $3x+3y+3z$ \anskey{$3(x+y+z)$} % \item True False % \begin{enumext}[nosep] % \item $\alpha > \delta$ \anskey{False} % \item \LaTeX2e\ is cool? \anskey{Very True!} % \end{enumext} % \item Related to Linux % \begin{enumext}[nosep] % \item You use linux? \anskey{Yes} % \item Usually uses the package manager? \anskey{Yes, \texttt{dnf}} % \item Rate the following package and class % \begin{enumext}[nosep] % \item \texttt{xsim-exam} \anskey{doesn't exist for now :(} % \item \texttt{xsim} \anskey{very good} % \item \texttt{exsheets} \anskey{obsolete} % \end{enumext} % \end{enumext} % \end{enumext} % % \smallskip % % Sometimes we are also interested in showing the \emph{\enquote{answers}} % along with the questions: % % \smallskip % % \begin{enumext}[save-ans=worksheet,columns=2,show-ans=true,nosep,save-ref=true] % \item Factor $x^{2}-2x+1$ \anskey{$\left(x-1\right)^{2}$} % \item Factor $3x+3y+3z$ \anskey{$3(x+y+z)$} % \item True False % \begin{enumext}[nosep] % \item $\alpha > \delta$ \anskey{False} % \item \LaTeX2e\ is cool? \anskey{Very True!} % \end{enumext} % \item Related to Linux % \begin{enumext}[nosep] % \item You use linux? \anskey{Yes} % \item Usually uses the package manager? \anskey{Yes, \texttt{dnf}} % \item Rate the following package and class % \begin{enumext}[nosep] % \item \texttt{xsim-exam} \anskey{doesn't exist for now :(} % \item \texttt{xsim} \anskey{very good} % \item \texttt{exsheets} \anskey{obsolete} % \end{enumext} % \end{enumext} % \end{enumext} % % \smallskip % % Or we are interested in referring to a specific question and its % \emph{\enquote{answer}}, for example: % % \smallskip % % The answer to \ref{worksheet:4} is \enquote{\getkeyans{worksheet:4}} % and the answer to \ref{worksheet:8} is \enquote{\getkeyans{worksheet:8}}. % % \smallskip % % Or we are interested in printing all the \emph{\enquote{answers}}: % % \smallskip % % \printkeyans{worksheet} % % \smallskip % % Another very common thing to use in my work is \emph{\enquote{multiple choice % questions}}, for example: % % \smallskip % % \begin{enumext}[save-ans=mytest,columns=2,nosep,save-ref=true,save-sep={ }] % \item First type of questions % \begin{keyans}[columns=2,noitemsep] % \item value % \item*[$x=5$] correct % \item value % \item value % \end{keyans} % \item Second type of questions % \begin{enumext}[no-store,label=\Roman*.,noitemsep] % \item $2\alpha+2\delta=90^{\circ}$ % \item $\alpha=\delta$ % \item $\angle EDF=45^{\circ}$ % \end{enumext} % \begin{keyans}[columns=2,noitemsep] % \item I only % \item II only % \item I and II only % \item* I and III only % \item I, II, and III % \end{keyans} % \item* Third type of questions % \begin{enumext}[no-store,list-offset=0.5cm,label=(\arabic*),noitemsep] % \item $2\alpha+2\delta=90^{\circ}$ % \item $\angle EDF=45^{\circ}$ % \end{enumext} % \begin{keyans}[columns=2,noitemsep] % \item value % \item value % \item*[some note] value % \item value % \item value % \end{keyans} % % \item Question with image and label below: % % \begin{keyanspic}[label-pos=below, layout-sty={3,2}] % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-b}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic*[A duck]{\includegraphics[scale=0.30]{example-image-duck}} % \end{keyanspic} % % \item Question with image on left side: % % \begin{keyans}[mini-env=0.5\linewidth, columns=1,noitemsep] % \item value % \item value % \item value % \item*[\enquote{other note}] correct % \item value % \miniright % \includegraphics[scale=0.15]{example-image-b} % \end{keyans} % \end{enumext} % % \smallskip % % Where what we are interested in the \mymeta{label} and a % \emph{\enquote{short note}} that we leave as an explanation, and then % print them: % % \smallskip % % \printkeyans{mytest} % % \smallskip % % The \mypkg*{enumext} package was created and designed to meet these % small requirements in the creation of \emph{\enquote{simple % worksheets}} and \emph{\enquote{multiple choice questions}}. % % \smallskip % % \begin{important}* % These \emph{\enquote{simple worksheets}} or \emph{\enquote{multiple % choice questions}} appear to be easy to obtain using a combination of % the \myenv{enumerate}, \myenv{minipage} and \myenv{multicols} % environments, but like many things, what \emph{\enquote{looks % simple}} is not so simple. % \end{important} % % \subsection{Description and usage} % % The \mypkg*{enumext} package defines enumerated environments using the % \myenv{list} environment provided by \hologo{LaTeX}, but % \emph{\enquote{does not redefine}} any internal commands associated with % it such as |\list|, |\endlist| or |\item| outside of the % \emph{\enquote{scope}} in which they are defined. % % \smallskip % % \begin{important}* % This package is NOT intend to replace the \myenv{enumerate} environment % nor replace the powerful \mypkg{enumitem}\cite{enumitem}, the approach % is intended to work without hindering either of them. % \end{important} % % \smallskip % % This package can be used with |xelatex|, |lualatex|, |pdflatex| and % the classical |latex>dvips>ps2pdf| and is present in \hologo{TeX} Live and \hologo{MiKTeX}, % use the package manager to install. For manual installation, download % \href{http://mirrors.ctan.org/macros/latex/contrib/enumext.zip}{enumext.zip} % and unzip it, run \lstinline[language=enumext-doc,basicstyle=\ttfamily]+luatex enumext.ins+ % and move all files to appropriate locations, then run |mktexlsr|. To produce the documentation run % \lstinline[language=enumext-doc,basicstyle=\ttfamily]+arara enumext.dtx+. % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single,language={}] enumext.sty > TDS:tex/latex/enumext/ enumext.pdf > TDS:doc/latex/enumext/ README.md > TDS:doc/latex/enumext/ enumext.dtx > TDS:source/latex/enumext/ enumext.ins > TDS:source/latex/enumext/ \end{examplecode} % \iffalse % % \fi % % The package is loaded in the usual way: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \usepackage{enumext} \end{examplecode} % \iffalse % % \fi % % \subsection{The concept of left margin} % % There is a direct relationship between the parameters |\leftmargin|, % |\itemindent|, \ics{labelwidth} and \ics{labelsep} plus an % \emph{\enquote{extra space}} that makes it difficult to obtain the % desired \emph{horizontal spaces} in a \myenv{list} environment. % Usually we don't want the \myenv{list} to go beyond the left margin of the % page, but since these four values are related, that causes a problem. % % The \mypkg{enumitem}\cite{enumitem} package adds the |\labelindent| parameter to % solve some of these problems. A simplified representation of this in % the figure \ref{fig:one}. % \setlength\intextsep{3pt} % \begin{figure}[ht] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (-0.5,6.175) --node[below,,text=lightgray,font=\footnotesize\ttfamily]{margin page} (2,6.175); % \draw[line width=0.5pt,dash pattern=on 2pt off 2pt,color=gray] (2,4.85) -- (2,7.5); % \draw[<->,color=gray] (2.0,7.0) --node[above,text=blue!75]{\texttt{\textbackslash{}labelindent}} (4.5,7.0); % \draw[<->,color=gray] (4.5,7.0) --node[above,text=blue!75]{\texttt{\textbackslash{}labelwidth}} (7.5,7.0); % \draw[<->,color=gray] (7.5,7.0) --node[above,text=blue!75]{\texttt{\textbackslash{}labelsep}} (9.5,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (4.5,6.5) rectangle (7.5,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.5,6.5) rectangle (9.5,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.5) rectangle (15,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.0) rectangle (15,6.35); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,5.5) rectangle (15,5.85); % \draw[<->,color=gray] (2.0,5.35) --node[below,text=blue!75]{\texttt{\textbackslash{}leftmargin}} (7.5,5.35); % \draw[<->,color=gray] (7.5,5.35) --node[below,text=blue!75]{\texttt{\textbackslash{}itemindent}} (9.5,5.35); % \end{tikzpicture} % \caption{Representation of horizontal lengths in \mypkg{enumitem}.} % \label{fig:one} % \end{figure} % % The \mypkg*{enumext} package does NOT provide a user interface to set the values for % |\leftmargin| and |\itemindent|, instead it provides the keys % \mykey{list-offset} and \mykey{list-indent} which internally set the % values for |\leftmargin| and |\itemindent|. The concepts of |\leftmargin| and |\itemindent| % are different in \mypkg*{enumext}. The figure \ref{fig:two} shows the visual representation of idea. % % \begin{figure}[ht] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (-0.5,6.175) --node[below,text=lightgray,font=\footnotesize\ttfamily]{margin page} (2,6.175); % \draw[line width=0.5pt,dash pattern=on 2pt off 2pt,color=gray] (2,4.85) -- (2,7.5); % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{list-offset}} (4.5,7.0); % \draw[<->,color=gray] (4.5,7.0) --node[above,text=blue!75]{\vphantom{p}\texttt{\textbackslash{}labelwidth}} (7.5,7.0); % \draw[<->,color=gray] (7.5,7.0) --node[above,text=blue!75]{\texttt{\textbackslash{}labelsep}} (9.5,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (4.5,6.5) rectangle (7.5,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.5,6.5) rectangle (9.5,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.5) rectangle (15,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.0) rectangle (15,6.35); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,5.5) rectangle (15,5.85); % \draw[<->,color=gray] (4.5,5.35) --node[below,text=optcolor]{\texttt{list-indent}} (9.5,5.35); % \end{tikzpicture} % \caption{Representation of horizontal lengths concept in \mypkg*{enumext}.} % \label{fig:two} % \end{figure} % % In this way we reduce a \emph{little} the amount of parameters we have to % pass. With the default values of keys \mykey{list-offset}, % \mykey{list-indent}, \mykey{labelwidth} and \mykey{labelsep} the lists % will have the (usually) expected output for \emph{\enquote{simple % worksheets}}. The figure \ref{fig:three} shows the visual representation. % % \begin{figure}[ht] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (-0.5,6.175) --node[below,text=lightgray,font=\footnotesize\ttfamily]{margin page} (2,6.175); % \draw [line width=0.5pt,dash pattern=on 2pt off 2pt,color=gray] (2,4.85) -- (2,7.5); % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=optcolor]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (15,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.0) rectangle (15,6.35); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.5) rectangle (15,5.85); % \draw[<->,color=gray] (2.0,5.35) --node[below,text=optcolor]{\texttt{list-indent}} (7.0,5.35); % \end{tikzpicture} % \caption{Default horizontal lengths \mykey{list-offset}=\mydim{0pt}, \mykey{list-indent}=\ics{labelwidth}+\ics{labelsep} in \mypkg*{enumext}.} % \label{fig:three} % \end{figure} % % \subsection{User interface} % \label{sec:interface} % % The user interface consists of two main list environments |enumext| % (vertical) and |enumext*| (horizontal), the environment |anskey*| and % the command |\anskey| to \emph{\enquote{store content}} and the % environments |keyans|, |keyans*| and |keyanspic| for multiple choice. % It also provides the commands |\getkeyans| to print individual % \emph{stored content}, |\printkeyans| and |\foreachkeyans| to print % all \emph{stored content}, |\miniright| for \myenv{minipage}, |\setenumext| % and |\setenumextmeta| to config \myoarg{key \textnormal{\textcolor{gray}{=}} val} options. % % \subsubsection{Internal counters} % % The package \mypkg*{enumext} uses internally the \icounter{enumXi}, % \icounter{enumXii}, \icounter{enumXiii}, \icounter{enumXiv} counters % for the four nesting levels of the \myenv*{enumext} environment, the % \icounter{enumXv} counter for the \myenv*{keyans} environment, the % \icounter{enumXvi} counter for the \myenv*{keyanspic} environment, % the counter \icounter{enumXvii} for \myenv*{enumext*} environment and the counter % \icounter{enumXviii} for \myenv*{keyans*} environment. % % \smallskip % % \begin{important}* % If any package defines these counters or they are user-defined % in the document, the package will return a fatal error and abort the % load. % \end{important} % % \subsubsection{Public dimension} % % The package \mypkg*{enumext} only provides a single public dimension % |\itemwidth| and is intended for user convenience only and is not % for internal use as such. The dimension |\itemwidth| is \emph{rigid length} % and contains the \emph{\enquote{width of the content}} of each |\item| % regardless of \mykey{labelwidth} and \mykey{labelsep}. % % \smallskip % % \begin{important}* % If any package defines |\itemwidth| or they are user-defined |\itemwidth| % in the document, the package will overwrite it without warning. % \end{important} % % \subsubsection{Support for \pkg{multicol}} % % The package provides direct support for using the \mypkg{multicol}\cite{multicol} % package. This allows to obtain directly a two-column output as shown % in the figure \ref{fig:fourth}. % % \begin{figure}[ht] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=optcolor]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (17.5,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.5) rectangle (11.5,6.35) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{column one} \\ % \textcolor{blue}{\emph{nested items}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (13.5,5.5) rectangle (17.5,6.35) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{column two} \\ % \textcolor{blue}{\emph{nested items}} % \end{tabular}}; % \draw[<->,color=gray] (2.0,5.35) --node[below,text=optcolor]{\texttt{list-indent}} (7.0,5.35); % \draw[<->,color=gray] (11.5,5.35) --node[below,text=optcolor]% % {\begin{tabular}{c} % \texttt{column-sep} \\ % \textcolor{blue}{\texttt{\textbackslash{}columnbreak}} % \end{tabular}} % (13.5,5.35); % \end{tikzpicture} % \caption{Representation of the two column output for a nested level in \myenv*{enumext} environment.} % \label{fig:fourth} % \end{figure} % % The \emph{\enquote{non starred}} version of the \myenv{multicols} % environment is always used together with the \ics{raggedcolumns} % command and is controlled by \mykey{columns} and \mykey{columns-sep} % keys. It can be used in all nesting levels of the % environment |enumext| and the environment |keyans| and can % together with the \mykey{mini-env} key. If you need to force a % start a new column \ics{columnbreak} must be used (see \S\ref{key:multi}). % % \smallskip % % \begin{important}* % The |\columnseprule| command is not available as a key and is set to % \emph{\enquote{zero}} for the inner levels and the \myenv*{keyans} environment. If the value of % this is set inside the document, it will affect \emph{\enquote{all environments}} that % use the \mykey{columns} key. % \end{important} % % \subsubsection{Support for \env{minipage}} % % The package provides direct support for \myenv{minipage} % environment, this allows you to obtain an output like the % one shown in figure \ref{fig:five}. % % \begin{figure}[!htbp] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=optcolor]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (17.5,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.5) rectangle (12.5,6.35) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage left} \\ % \textcolor{blue}{\emph{nested list}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (14.5,5.5) rectangle (17.5,6.35) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage right} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % \draw[<->,color=gray] (2.0,5.35) --node[below,text=optcolor]{\texttt{list-indent}} (7.0,5.35); % \draw[<->,color=gray] (7.0,5.35) --node[below,text=optcolor]{\texttt{mini-env}} (12.5,5.35); % \draw[<->,color=gray] (12.5,5.35) --node[below,text=optcolor]% % {\begin{tabular}{c} % \texttt{mini-sep} \\ % \textcolor{pkgcolor}{\texttt{\textbackslash{}miniright}} % \end{tabular}} (14.5,5.35); % \end{tikzpicture} % \caption{Representation of the \mykey{mini-env} output for a nested level \myenv*{enumext} environment.} % \label{fig:five} % \end{figure} % % The \myenv{minipage} environments on \emph{\enquote{left side}} and % \emph{\enquote{right side}} is always used with \emph{\enquote{aligned % on top}} |[t]|. It can be used in all nesting levels of the % environment |enumext| and the environment |keyans| and is controlled % by \mykey{mini-env} and \mykey{mini-sep} keys. In order to switch from % the \emph{\enquote{left}} side \myenv{minipage} environment to the % \emph{\enquote{right}} side one must use the command |\miniright| % (see~\S\ref{key:mini}). % % \subsubsection{The \cs[no-index]{label} and \cs[no-index]{ref} system} % % This package provides a user interface like the % \mypkg{enumitem}\cite{enumitem} package to customize the references % which is activated by the \mykey{ref} key (\S\ref{subsec:label-and-ref}), the standard \hologo{LaTeX} % \ics{label} and \ics{ref} commands work as usual. % It also provides an \emph{\enquote{internal reference}} system for the % \emph{\enquote{stored content}} by means of the key \mykey{save-ref} % (\S\ref{subsec:label-ref}) when the key \mykey{save-ans} (\S\ref{subsec:storage-keys}) is active. % % \subsubsection{Support for \cs[no-index]{footnote}}\label{doc:footnote} % % The \myenv*{enumext*} and \myenv*{keyans*} environments and the % \mykey{mini-env} key use the \myenv{minipage} environment in their % implementation but in a transparent way for the user, i.e. it is only % used for typesetting and not directly. The \mypkg*{enumext} package provides an \emph{internal implementation} for the % command |\footnote| compatible with the \mypkg{hyperref} package to % work in the same way as if it were used anywhere in the document. % % \newpage % % Unfortunately, if \emph{tagging} \texttt{PDF} is not enabled, it will % not produce the expected \emph{\enquote{links}} because the internal % implementation uses |\footnotetext|\myoarg{number} and |\footnotemark|\myoarg{number}\mymarg{text} % and support for these is limited by the \mypkg{hyperref} package. % % \smallskip % % The best way to solve this if \emph{tagged} \texttt{PDF} is NOT active % is to use Jean-François Burnol \mypkg{footnotehyper}\cite{footnotehyper} % package, it will support keeping the \emph{\enquote{links}} if % \mypkg{hyperref} is loaded with the |hyperfootnotes=true| option (default). % Load it is as follows: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \IfDocumentMetadataTF{ } { \usepackage{footnotehyper} \makesavenoteenv{enumext} \makesavenoteenv{enumext*} } \end{examplecode} % \iffalse % % \fi % % \begin{important} % At the moment the \mypkg{footnotehyper} package is not compatible % with \emph{tagged} \texttt{PDF}. % \end{important} % % \section{The environments provided} % % The package \mypkg*{enumext} provides two main list environments, the % \emph{vertical} environment \myenv*{enumext} and the \emph{horizontal} % environment \myenv*{enumext*}. % % \vspace*{-\baselineskip} % % \begin{function}{enumext,enumext*} % \begin{minipage}[t]{0.45\linewidth} % \envexamp{enumext} % \end{minipage}\hfill % \begin{minipage}[t]{0.45\linewidth} % \envexamp{enumext*} % \end{minipage} % \end{function} % % \medskip % % \subsection{The environment \texttt{enumext}}\label{sec:envenumext} % % The \myenv*{enumext} is an environment that works in the same way as % the standard \myenv{enumerate} environment provided by \hologo{LaTeX}, % \ics*{item} and \ics*{item}\myoarg{custom} commands work in % the usual way. The environment can be nested with at most \emph{\enquote{four levels}} % and the options can be configured globally using \ics*{setenumext} % command and locally using \myoarg{key \textnormal{\textcolor{gray}{=}} val} % in the environment. % % \subsubsection*{Example with \texttt{columns=2}} % % \begin{enumext}[columns=2, topsep=0pt] % \item This text is in the first level. % \begin{enumext} % \item This text is in the second level. % \begin{enumext} % \item This text is in the third level. % \begin{enumext} % \item This text is in the fourth level. % \end{enumext} % \end{enumext} % \end{enumext} % \item[X] This text is in the first level. % \item* This text is in the first level. % \end{enumext} % % \subsection{The environment \texttt{enumext*}} % % The \myenv*{enumext*} is a \emph{horizontal list environment} % similar to the \myenv{shortenumerate} or \myenv{tasks} environments % provided by the \mypkg{shortlst}\cite{shortlst} and \mypkg{tasks}\cite{tasks} % packages, \ics*{item} and \ics*{item}\myoarg{custom} work as usual. % The options can be configured globally using \ics*{setenumext} command % and locally using \myoarg{key \textnormal{\textcolor{gray}{=}} val} % in the environment. % % \smallskip % % Some considerations to take into account for this environment: % % \begin{itemize}[nosep,parsep=1pt,topsep=2pt] % \item The environment cannot be nested within itself or in the % environment \myenv*{keyans*}, but it can be nested within % \myenv*{enumext} and vice versa. % % \item Each \emph{\enquote{item content}} in the environment is placed % within a \myenv{minipage} environment whose \emph{width} is stored % in the dimension |\itemwidth| that NOT includes \mykey{labelwith}, % \mykey{labelsep}, only the \emph{width of the content}. % % \item You cannot have floating environments like \myenv{figure} or % \myenv{table} but \ics{footnote} with \mypkg{hyperref} support is % supported if the \mypkg{footnotehyper} package is loaded (see \S\ref{doc:footnote} for full support). % % \item You cannot have any standard list environments like \myenv{itemize}, % \myenv{enumerate}, \myenv{description}, \myenv{quote}, \myenv{quotation}, % \myenv{verse}, \myenv{center}, \myenv{flushleft}, \myenv{flushright}, % \myenv{verbatim}, \myenv{tabbing}, \myenv{trivlist}, \myenv{list} % and all environments created with |\newtheorem|. % \end{itemize} % % \subsubsection*{Example with \texttt{columns=2}} % % \begin{enumext*}[columns=2] % \item This text is in the first level. % \item This text is in the first level. % \item[X] This text is in the first level. % \item* This text is in the first level. % \end{enumext*} % % \subsection{The command \cs[no-index]{item*}} % % \vspace*{-\baselineskip} % % \begin{function}{\item*} % \begin{syntax} % \ics*{item*}\myoarg{symbol}\myoarg{offset} % \end{syntax} % The \ics*{item*}, \ics*{item*}\myoarg{symbol} and \ics*{item*}\myoarg{symbol}\myoarg{offset} % works like the numbered |\item|, but placing a \mymeta{symbol} to % the \emph{\enquote{left}} of the \mymeta{label} separated from it by % the \mymeta{offset} set by the the \emph{second optional argument}. % % \smallskip % % The \emph{starred argument} ‘|*|’ cannot be separated by spaces % ‘\verb*| |’ from the command, i.e. \ics*{item*} and the % \emph{first optional argument} does \enquote{NOT} support % \emph{verbatim content}. Can be configure with the keys % \mykey{item-sym*} and \mykey{item-pos*} locally in the environment % or globally using \ics*{setenumext} command (\S\ref{sec:setenumext}). % \end{function} % % \smallskip % % \begin{important}* % The behavior of \ics*{item*} in the \myenv*{enumext} and \myenv*{enumext*} environments is NOT % the same as in the \myenv*{keyans} and \myenv*{keyans*} environments. % \end{important} % % \subsubsection{Keys for \cs[no-index]{item*}} % % \keyexamp{item-sym\textcolor{MediumOrchid}{*}}{symbol}{\textbackslash{}textasteriskcentered} % Sets the \emph{symbol} to be displayed in the \emph{\enquote{left}} of the % box containing the current \mymeta{label} set by \mykey{labelwidth} key for \ics*{item*} in % \myenv*{enumext} and \myenv*{enumext*}. The \emph{symbol} can be in % \emph{text} or \emph{math} mode, for example \mykey{item-sym*}|={$\star$}|. % % \smallskip % % \keyexamp{item-pos\textcolor{MediumOrchid}{*}}{rigid length}{by levels} % Sets the \emph{offset} between the box containing the % current \mymeta{label} defined by \mykey{labelwidth} key and the % \mymeta{symbol} set by \mykey{item-sym*} key. The default values are % set by \mykey{labelsep} key at each level. If positive values are % passed it will \emph{offset to the left} and if negative values are % passed it will \emph{offset to the right}. % % \subsection{The command \cs[no-index]{item} in \texttt{enumext*}} % % The \ics*{item} command for the \myenv*{enumext*} environment provides % an \emph{\enquote{first optional argument}} \ics*{item}\myparg{columns} which \emph{\enquote{joins items}} % between columns. Let's consider the following examples adapted directly from % the \mypkg{task} package: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \begin{enumext*}[widest=10,columns=4] \item The first \item* The second \item The third \item The fourth \item(3)* The fifth item is way too long for this and needs three columns \item The sixth \item The seventh \item(2)[X] The eighth item is way too long for this and needs two columns (\the\itemwidth) \item The ninth \item[Z] The tenth (\the\itemwidth) \end{enumext*} \end{examplecode} % \iffalse % % \fi % % \begin{enumext*}[widest=10,columns=4] % \item The first % \item* The second % \item The third % \item The fourth % \item(3)* The fifth item is way too long for this and needs three columns % \item The sixth % \item The seventh % \item(2)[X] The eighth item is way too long for this and needs two columns (\the\itemwidth) % \item The ninth % \item[Z] The tenth (\the\itemwidth) % \end{enumext*} % % \section{The command \cs{setenumext}} % \label{sec:setenumext} % % \vspace*{-10pt} % % \begin{function}{\setenumext} % \begin{minipage}[t]{0.45\linewidth} % \cmdexamp{setenumext}{key \textnormal{\textcolor{gray}{=}} val} % \cmdexamp{setenumext}[enumext\textnormal{\textcolor{gray}{,}} level]{key \textnormal{\textcolor{gray}{=}} val} % \cmdexamp{setenumext}[enumext*]{key \textnormal{\textcolor{gray}{=}} val} % \cmdexamp{setenumext}[keyans]{key \textnormal{\textcolor{gray}{=}} val} % \end{minipage}\hfill % \begin{minipage}[t]{0.45\linewidth} % \cmdexamp{setenumext}[keyans*]{key \textnormal{\textcolor{gray}{=}} val} % \cmdexamp{setenumext}[print\textnormal{\textcolor{gray}{,}} level]{key \textnormal{\textcolor{gray}{=}} val} % \cmdexamp{setenumext}[print\textnormal{\textcolor{gray}{,}} \textnormal{\textcolor{red}{*}}]{key \textnormal{\textcolor{gray}{=}} val} % \cmdexamp{setenumext}[print*]{key \textnormal{\textcolor{gray}{=}} val} % \end{minipage} % % \smallskip % % The command \ics*{setenumext} sets the \mymeta{keys} on a global basis % for environments \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans}, % \myenv*{keyans*} and the \ics*{printkeyans} command. % It can be used both in the preamble and in the body of the document % as many times as desired. % \end{function} % % \smallskip % % The \mymeta{keys} set in the \emph{optional argument} of environments and % commands have the \emph{highest precedence}, overriding both % options passed by \ics*{setenumext}. If the \emph{optional argument} is not % passed, the first level of the environment \myenv*{enumext} will be % taken by default. % % \smallskip % % \begin{important}* % The key \mykey{save-ans} that activate the \emph{\enquote{storage % system}} must NOT be passed through this command and must be passed % directly in the \emph{optional argument} of the \emph{\enquote{first level}} % of the environment in which they are executed. % \end{important} % % \smallskip % % \section{The command \cs[no-index]{setenumextmeta}} % % \vspace*{-\baselineskip} % % \begin{function}{\setenumextmeta} % \begin{syntax} % \ics*{setenumextmeta} \mymarg{key name}\mymarg{key-one \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} key-two \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} \dots} % \ics*{setenumextmeta}|*|\mymarg{key name}\mymarg{key-one \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} key-two \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} \dots} % \ics*{setenumextmeta} \myoarg{enumext\textnormal{\textcolor{MediumOrchid}{\texttt{*}}}}\mymarg{key name}\mymarg{key-one \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} key-two \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} \dots} % \ics*{setenumextmeta} \myoarg{enumext\textnormal{\textcolor{gray}{,}} level}\mymarg{key name}\mymarg{key-one \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} key-two \textnormal{\textcolor{gray}{=}} val\textnormal{\textcolor{gray}{,}} \dots} % \end{syntax} % The command \ics*{setenumextmeta} adds a new \emph{\enquote{meta-key}} % for the environments \myenv*{enumext} and \myenv*{enumext*}, the % \mymarg{key name} must be different from those defined by the package. % If the \emph{optional argument} is not passed, the new \emph{\enquote{meta-key}} % will be created for the \emph{\enquote{first level}} of the environment % \myenv*{enumext}. % \end{function} % % \smallskip % % The \emph{starred argument} ‘|*|’ will create the new \emph{\enquote{meta-key}} % for the environment \myenv*{enumext*} and for all levels of the % environment \myenv*{enumext}. For example: |\setenumextmeta*{midsep}{topsep=3pt, partopsep=0pt}| % will create a new key |midsep| available for all levels of the % \myenv*{enumext} environment and the \myenv*{enumext*} environment % and we can use it like any other key so |\begin{enumext}[midsep]| % and |\begin{enumext*}[midsep]| will be valid. % % \section{The \texttt{keyval} system} % % The \mymeta{key = val} system used by the \mypkg*{enumext} package is implemented % using \mypkg{l3keys} so it must be taken into consideration that those % keys marked as \emph{\enquote{value forbidden}}, that is \mymeta{key} is % different from \mymeta{key=}. % % \smallskip % % All \mymeta{keys} described in this section are available for the % \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and \myenv*{keyans*} % environments with the exception of the keys \mykey{series}, \mykey{resume}, % \mykey{resume*} which are only available for the \emph{\enquote{first level}} % of the environments \myenv*{enumext} and \myenv*{enumext*}; and the keys % \mykey{mini-right}, \mykey{mini-right*} which are only available for % the \myenv*{enumext*} and \myenv*{keyans*} environments. % % \smallskip % % All \mymeta{keys} related to vertical or horizontal spacing accept a % \emph{\enquote{skip}} or \emph{\enquote{dim}} expression if passed % between braces, i.e. you do not need to use |\dimeval| or |\dimexpr| % to perform calculations. % % \smallskip % % \begin{important}* % It should be kept in mind that using any \mymeta{key} that sets % a \emph{rubber lengths} or \emph{rigid lengths} for vertical or % horizontal space on a level will influence the vertical and horizontal % space for \emph{inners levels} and \myenv*{keyans}, \myenv*{keyans*} and % \myenv*{keyanspic} environments. % \end{important} % % \smallskip % % \subsection{Keys for \texttt{label} and \texttt{ref}}\label{subsec:label-and-ref} % % \keyexamp*{mode-box}{value forbidden}{not used} % This is a \emph{\enquote{switch-key}} that does not receive an % argument and is \enquote{only} available for the \emph{\enquote{first level}} % of the \myenv*{enumext} environment and the \myenv*{enumext*} environment. % When this is set the \mykey{label}, \mykey{font}, \mykey{wrap-label} % and \mykey{wrap-label*} keys are executed within |\makebox| for the % \myenv*{enumext} and \myenv*{keyans} environments. % % \smallskip % % \begin{important} % This key is intended for compatibility with \emph{tagged} \texttt{PDF} % and is forcibly \emph{\enquote{enabled}} when |\DocumentMetadata| is % present. If you want to get the same document output whether |\DocumentMetadata| % is active or not, you must enable this key. % \end{important} % % \smallskip % % \begin{important}* % In the \myenv*{enumext*} and \myenv*{keyans*} environments |\makelabel| % are redefined using |\makebox| by default. If \myenv*{enumext} or % \myenv*{keyans} is used in the \myenv*{enumext*} environment the key % must be activated manually. % \end{important} % % \smallskip % % \keyexamp{label} % {\textnormal % {\ilabel{alph*} \textcolor{lightgray}{\textbar} \ilabel{Alph*} % \textcolor{lightgray}{\textbar} \ilabel{arabic*} % \textcolor{lightgray}{\textbar} \ilabel{roman*} % \textcolor{lightgray}{\textbar} \ilabel{Roman*}} % }{by levels} % % \smallskip % % Sets the \mymeta{label} that will be printed at the \emph{current % level}. The default value for the first level of the environments % \myenv*{enumext} and \myenv*{enumext*} are \ilabel{arabic*.}, for % second level are \ilabel*{alph*)}, for third level are \ilabel{roman*.} % and for fourth level are \ilabel{Alph*.}. For \myenv*{keyans} % and \myenv*{keyans*} environments the default value is \ilabel{Alph*)}. % % \smallskip % % \begin{important}* % This key is intended to give the basic structure with which the % \mymeta{label} will be displayed, and the form in which it is % used by standard \emph{\enquote{label and ref}} and the % \emph{\enquote{internal label and ref}} system with the % \mykey{save-ref} key. You cannot use commands with \mymeta{label} as an % argument, for example |\emph|\mymarg{\textnormal{\ilabel{alph*}}} will return an % error. For full customization of how \mymeta{label} is displayed use % the \mykey{font}, \mykey{wrap-label} and/or \mykey{wrap-label*} keys. % \end{important} % % \smallskip % % \keyexamp{labelsep}{rigid length}{\mydim{0.3333}em} % Sets the \emph{horizontal space} between the box containing the % current \mymeta{label} defined by \mykey{label} key and the text of an % item on the first line. Internally sets the value of \ics{labelsep} for % the current level. % % \smallskip % % \keyexamp{labelwidth}{rigid length}{by label} % Sets the \emph{width} of the box containing the current \mymeta{label} set % by \mykey{label} key. Internally sets the value of \ics{labelwidth} for the current % level. The default values are calculated by means of the \emph{width} % of a box by setting a \emph{value} to the current counter using ‘\mydim{0}’ for % \ilabel{arabic*}, ‘|M|’ for \ilabel{Alph*}, ‘|m|’ for \ilabel{alph*}, ‘|VIII|’ % for \ilabel{Roman*} and ‘|viii|’ for \ilabel{roman*}. % % \smallskip % % \keyexamp{widest}{integer \textnormal{\textcolor{lightgray}{\textbar}} string}{empty} % Sets the \mykey{labelwidth} key pass the \mymeta{integer} or converting % the \mymeta{string} of the form |\Alph|, |\alph|, |\Roman| or |\roman| % to a \emph{value} for the current counter defined by \mykey{label} key, % then calculating the \emph{width} by means of a box. For example |widest={XXIII}| % or |widest={23}| are equivalent. This key is useful when the default % values of the \mykey{labelwidth} key are smaller than those actually used. % % \smallskip % % \keyexamp{font}{font commands}{empty} % Sets the \emph{font style} for the current \mymeta{label} defined by \mykey{label} key. % For example |font={\bfseries\small}|. % % \smallskip % % \keyexamp{align}{left \textnormal{\textcolor{lightgray}{\textbar}} right \textnormal{\textcolor{lightgray}{\textbar}} center}{left} % Sets the \emph{aligned} of \mymeta{label} defined by \mykey{label} % key on the current level in the label box. % % \smallskip % % \newsavebox{\hashbox} % \begin{lrbox}{\hashbox} % \lstinline[language=enumext-doc,basicstyle=\ttfamily]+{#1}+ % \end{lrbox} % % \keyexamp{wrap-label}{code{} \space\usebox{\hashbox} more code}{empty} % % \smallskip % % Wraps the \emph{current} \mymeta{label} defined by \mykey{label} key referenced by |{#1}|. % The \mymarg{code} must be passed between braces. % This key does not modify the value set by the \mykey{labelwidth} key % and is applied only on \ics*{item} and \ics*{item*}. % When using it in the \ics*{setenumext} command it is necessary to use the % \emph{double hash} ‘|{##1}|’. For example |wrap-label={\fbox{#1}}| % or you can create a command: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=none] \NewDocumentCommand \mywrap { s m } { \IfBooleanTF{#1} {\textcolor{red}{\textbf{Q}}\textcolor{blue}{\textbf{.}}\textcolor{gray}{#2}} {\textcolor{blue}{\textbf{Q}}\textcolor{red}{\textbf{.}}\textcolor{gray}{#2}} } \end{examplecode} % \iffalse % % \fi % % and then pass it through the key |wrap-label={\mywrap{#1}}| or |wrap-label={\mywrap*{#1}}|. % % \smallskip % % \keyexamp{wrap-label\textcolor{MediumOrchid}{*}}{code{} \space\usebox{\hashbox} more code}{empty} % % \smallskip % % The same as the \mykey{wrap-label} key but also applies on \ics*{item}\myoarg{custom}. % % \newpage % % \newsavebox{\refboxsample} % \begin{lrbox}{\refboxsample} % \small\textcolor{gray}{\ttfamily\{}\textnormal{\small\ilabel{alph*}\textcolor{lightgray}{\textbar} \ilabel{Alph*}\textcolor{lightgray}{\textbar} \ilabel{arabic*}\textcolor{lightgray}{\textbar} \ilabel{roman*}\textcolor{lightgray}{\textbar} \ilabel{Roman*}}\textcolor{gray}{\ttfamily\}} % \end{lrbox} % \keyexamp{ref}{code{} \space\usebox{\refboxsample} more code}{empty} % % Modifies the way \emph{cross references} are displayed. The % \mykey{label} key sets the default form of the \emph{cross references}, % by using this key you can define a different format, for example: % \mykey{ref}|=\emph|\mymarg{\textnormal{\ilabel{alph*}}} is valid. % % \smallskip % % Internally it renews the command associated with each counter when it % is executed, i.e., in the environment \myenv*{enumext} the command |\theenumXi| % is modified when the key is executed at the first level, |\theenumXii| % when it is executed at the second level and |\theenumXiii| together % with |\theenumXiv| when it is executed at the % third and fourth levels. % % \smallskip % % \begin{important}* % This must be kept in mind, since the values set by the \mykey{label} and % \mykey{ref} keys are not cumulative by levels, so if you have used the \mykey{ref} % key in the first level and then want to associate the counter with % \mykey{label} or \mykey{ref} in the second level you must use the direct commands, % i.e. |\arabic{eunumXi}| to indicate the count of the first level % instead of using |\theenumXi|. % \end{important} % % \subsection{Keys for spaces} % % \keyexamp{show-length}{true \textnormal{\textcolor{lightgray}{\textbar}} false}{false} % Displays on the terminal the values for \emph{all list parameters} at the current level. % For \emph{vertical spaces} show the values of |\topsep|, |\itemsep|, |\parsep| and |\partopsep|. % For \emph{horizontal spaces} show the values of |\labelwidth|, |\labelsep|, |\itemindent|, |\listparindent| and |\leftmargin|. % % \subsubsection{Vertical spaces} % % \keyexamp{topsep}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{by levels} % % \smallskip % % Set the \emph{vertical space} added to both the top and bottom of the list. % Internally sets the value of \ics{topsep} for the current level. % The default value for the first level of the environments % \myenv*{enumext} and \myenv*{enumext*} are \mydim{8.0pt plus 2.0pt minus 4.0pt}, % for second level are \mydim{4.0pt plus 2.0pt minus 1.0pt}, for third and % fourth level are \mydim{2.0pt plus 1.0pt minus 1.0pt}. For \myenv*{keyans} % and \myenv*{keyans*} environments the default value is \mydim{4.0pt plus 2.0pt minus 1.0pt}. % % \smallskip % % \keyexamp{parsep}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{by levels} % % \smallskip % % Set the \emph{vertical space} between paragraphs within an item. % Internally sets the value of \ics{parsep} for the current level. % The default value for the first level of the environments \myenv*{enumext} % and \myenv*{enumext*} are \mydim{4.0pt plus 2.0pt minus 1.0pt}, % for second level are \mydim{2.0pt plus 1.0pt minus 1.0pt}, for third and % fourth level are \mydim{0pt}. For \myenv*{keyans} and \myenv*{keyans*} % environments the default value is \mydim{2.0pt plus 1.0pt minus 1.0pt}. % % \smallskip % % \begin{important}* % In the \myenv*{enumext*} and \myenv*{keyans*} environments this value % is passed to |\parskip| within the \myenv{minipage} environment where % \emph{\enquote{item content}} is placed. % \end{important} % % \smallskip % % \keyexamp{partopsep}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{by levels} % % \smallskip % % Set the \emph{vertical space} added, beyond \mykey{topsep}, to the \enquote{top} and \enquote{bottom} % of the entire environment if the environment instance is preceded by a \emph{\enquote{blank % line}} or |\par| command. Internally sets the value of \ics{partopsep} for the current level. % The default values for first and second level in environment % \myenv*{enumext} are \mydim{2.0pt plus 1.0pt minus 1.0pt}, % for third and fourth level are \mydim{1.0pt minus 1.0pt}. % For the \myenv*{keyans} environment the default value is \mydim{2.0pt % plus 1.0pt minus 1.0pt}, and for the \myenv*{keyans*} and % \myenv*{enumext*} environments it is available but \emph{without} % effect. % % \smallskip % % \begin{important}* % The value of this parameter also affects the \emph{inner levels} and the % environments \myenv*{keyans}, \myenv*{keyanspic} and \myenv*{keyans*}. % Caution should be taken with \emph{\enquote{blank lines}} or |\par| % command \emph{\enquote{before}} each environment or nested level when % formatting the source code of document. \hologo{TeX} will enter \mymeta{vertical mode} % and apply this value to the \enquote{top} and \enquote{bottom} the % environment or nested level. % \end{important} % % \smallskip % % \keyexamp{itemsep}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{by levels} % Set the \emph{vertical space} between items, beyond the \mykey{parsep}. % Internally sets the value of \ics{itemsep} for the current level. % The default value for the first level of the environments \myenv*{enumext} % and \myenv*{enumext*} are \mydim{4.0pt plus 2.0pt minus 1.0pt}, % for the rest of the levels are \mydim{2.0pt plus 1.0pt minus 1.0pt}. % For \myenv*{keyans} and \myenv*{keyans*} environments the default % value is \mydim{4.0pt plus 2.0pt minus 1.0pt}. % % \smallskip % % \begin{important}* % In the \myenv*{enumext*} and \myenv*{keyans*} environments this value % corresponds to the separation between rows. % \end{important} % % \smallskip % % \keyexamp*{noitemsep}{value forbidden}{not used} % This is a \emph{\enquote{meta-key}} that does not receive an argument. Set % \mykey{itemsep} and \mykey{parsep} equal to \mydim{0pt} the entire level of environment. % % \smallskip % % \keyexamp*{nosep}{value forbidden}{not used} % This is a \emph{\enquote{meta-key}} that does not receive an argument. Sets all keys % for vertical spacing equal to \mydim{0pt} the entire level of environment. % % \smallskip % % \keyexamp*{base-fix}{value forbidden}{not used} % % \smallskip % % This is a \emph{\enquote{switch-key}} that does not receive an % argument available \emph{only} for the \emph{\enquote{first level}} of environment % \myenv*{enumext}. Fix the \emph{baseline} when an environment \myenv*{enumext} % is nested in \myenv*{enumext*} and there is no material between the % |\item| and the start of the environment for example |\item \begin{enumext}| % within the environment \myenv*{enumext*}. Internally sets the keys \mykey{topsep}, % \mykey{above} and \mykey{above}|*| at \mydim{0pt}. % % \smallskip % % \begin{important}* % This key is provided as a way to work around this minor issue, but you % should be aware that if for some reason you have the \mykey{itemindent} % key set in the \myenv*{enumext*} environment it will be lost and you % will need to adjust it using the \mykey{list-offset} key in the % \myenv*{enumext} environment. % \end{important} % % \newpage % % \begin{important}* % The following \mymeta{keys} should be used with \emph{\enquote{caution}}, they % are intended to be used at the \enquote{top} and \enquote{bottom} of % the environment when the \mykey{columns} or \mykey{mini-env} keys do % not provide adequate \emph{vertical spaces}. % The values ​​passed can be \emph{rubber} or \emph{rigid} lengths, the % way they are applied is the way you differ, using the \emph{star} ‘|*|’ % \mymeta{keys} applies |\vspace*| so that \hologo{LaTeX} does % \emph{not discard} this space at page break. % \end{important} % % \smallskip % % \keyexamp{above}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{not used} % % \smallskip % % Set the \emph{extra vertical space} added, beyond \mykey{topsep}, to % the top of the entire level of environment. This key is intended to % give a \emph{\enquote{fine adjustment}} of the vertical space % \emph{\enquote{above}} the environment without hindering the value of % the \mykey{topsep} key. The space is added with |\vspace| so is % \emph{\enquote{discardable}}. % % \keyexamp{above\textcolor{MediumOrchid}{*}}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{not used} % % \smallskip % % Set the \emph{extra vertical space} added, beyond \mykey{topsep}, to % the top of the entire level of environment. This key is intended to % give a \emph{\enquote{fine adjustment}} of the vertical space % \emph{\enquote{above}} the environment without hindering the value of % the \mykey{topsep} key. The space is added with |\vspace*| so is % \emph{\enquote{not discardable}}. % % \smallskip % % \keyexamp{below}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{not used} % % \smallskip % % Set the \emph{extra vertical space} space added, beyond \mykey{topsep}, to % the bottom of the entire level of environment. This key is intended to % give a \emph{\enquote{fine adjustment}} of the vertical space on the % \emph{\enquote{below}} the environment without hindering the value of % the \mykey{topsep} key. The space is added with |\vspace| so is % \emph{\enquote{discardable}}. % % \smallskip % % \keyexamp{below\textcolor{MediumOrchid}{*}}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{not used} % % \smallskip % % Set the \emph{extra vertical space} space added, beyond \mykey{topsep}, to % the bottom of the entire level of environment. This key is intended to % give a \emph{\enquote{fine adjustment}} of the vertical space on the % \emph{\enquote{below}} the environment without hindering the value of % the \mykey{topsep} key. The space is added with |\vspace*| so is % \emph{\enquote{not discardable}}. % % \subsubsection{Horizontal spaces} % % \keyexamp{list-offset}{rigid length}{\mydim{0}pt} % Sets the \emph{horizontal translation} of the entire environment level from the left edge % of the box defined by the \mykey{labelwidth} key. Internally sets the values of % |\leftmargin| and |\itemindent| for the current level. % % \smallskip % % \keyexamp{list-indent}{rigid length}{labelwidth + labelsep} % Sets the \emph{indentation} of the whole environment under the box defined by % \mykey{labelwidth} and \mykey{labelsep} keys. Internally sets the value of % |\leftmargin| and |\itemindent| for the current level. % If |list-indent=|\mydim{0pt} is set in the environments \myenv*{enumext} % and \myenv*{keyans} the \mymeta{label} will be part of the text, separated % by the value of the \mykey{labelsep} key and the \emph{first word}, in % simple terms it will look like a \emph{\enquote{common paragraph}}. % % \smallskip % % \begin{important}* % The \myenv*{enumext*} and \myenv*{keyans*} environments are % implemented using |\makebox| and \myenv{minipage} which causes % \emph{\enquote{list indent}} to always be equal to the value passed to % \mykey{labewdith} plus \mykey{labelsep}. Passing a value to this key is % equivalent to setting the value for the \mykey{list-offset} key. % \end{important} % % \smallskip % % \keyexamp{itemindent}{rigid length}{\mydim{0}pt} % % \smallskip % % Sets the extra \emph{horizontal indentation}, beyond \mykey{labelsep}, % of the \emph{\enquote{first line}} off each |\item| that is not followed % by a \emph{\enquote{blank line}} or the |\par| command . This value must % be greater than or equal to \mydim{0pt} and is applied internally using % |\hspace| \emph{without} modifying the value of |\itemindent|. % % \smallskip % % \begin{important}* % This key is intended for the \myenv*{enumext*} and \myenv*{keyans*} % environments where, by their implementation, it is not possible to % adjust \mykey{labelwidth} and \mykey{list-indent} \emph{without} % modifying the output. If you use \myenv*{enumext} or \myenv*{keyans} % and want to get around the \emph{blank line} limitation or the |\par| % command followed by |\item| you can modify \mykey{labelwidth} and % \mykey{list-indent} and get the same effect. % \end{important} % % \smallskip % % \keyexamp{rightmargin}{rigid length}{\mydim{0}pt} % % \smallskip % % Set the \emph{horizontal space} between the right margin of the environment and the % right margin of the enclosing environment, the value it takes must be % greater than or equal to \mydim{0pt}. Internally sets the value of % \ics{rightmargin} for the current level. % % \smallskip % % \keyexamp{listparindent}{rigid length}{\mydim{0}pt} % Sets the \emph{horizontal space} indentation, beyond \mykey{list-indent}, % for second and subsequent paragraphs within a list item. Internally % sets the value of \ics{listparindent} for the current level. % % \smallskip % % \begin{important}* % In the \myenv*{enumext*} and \myenv*{keyans*} environments this value % is passed to |\parindent| within the \myenv{minipage} environment where % \emph{\enquote{item content}} is placed. % \end{important} % % \smallskip % % \subsection{Keys for add \texttt{code}} % % The following \mymeta{keys} should be used with \emph{\enquote{caution}}, % they are intended to inject \mymarg{code} into different parts of the % defined environments. We must keep in mind that the defined % environments are based on the \myenv{list} base environment provided by % \hologo{LaTeX} which is defined (simplified) as plain form |\list|\mymarg{arg one}\mymarg{arg two}. % Using the \mykey{before*} key does not allow access to the \myenv{list} % parameters defined by \myoarg{key % \textnormal{\textcolor{gray}{=}} val}. % % \smallskip % % \keyexamp{before}{code}{not used} % Execute \mymarg{code} \emph{\enquote{before}} the % environment starts. The \mymarg{code} must be passed between braces, is executed % \emph{\enquote{after}} performing all calculations related to the % \emph{list parameters} in the environment and the parameters sets by % \myoarg{key \textnormal{\textcolor{gray}{=}} val} that is, in the second argument of the list after setting all the parameters % |\begin{list}|\mymarg{arg one}|{|\mymeta{arg two}\mymarg[cbc=pkgcolor,ac=araracolor]{code}|}|. % % \smallskip % % \keyexamp{before\textcolor{MediumOrchid}{*}}{code}{not used} % Execute \mymarg{code} \emph{\enquote{before}} the % environment starts. The \mymarg{code} must be passed between braces, is executed % \emph{\enquote{before}} performing all calculations related to the \emph{list % parameters} and \myoarg{key \textnormal{\textcolor{gray}{=}} % val} sets in the environment that is, % before the arguments defining the environment are executed: % \mymarg[type=tt,cbc=pkgcolor,ac=araracolor]{code}|\begin{list}|\mymarg{arg % one}\mymarg{arg two}. % % \smallskip % % \keyexamp{first}{code}{not used} % Executes \mymarg{code} when \emph{\enquote{starting}} the % environment. The \mymarg{code} must be passed between % braces, is executed right \emph{\enquote{after}} all \emph{list % parameters} are done, after the second argument of list, just before the first occurrence of \ics*{item}: % |\begin{list}|\mymarg{arg one}\mymarg{arg two}\mymarg[cbc=pkgcolor,ac=araracolor]{code}|\item|. % % \smallskip % % \begin{important}* % Keep in mind that the code set in this key will affect the entire % \emph{\enquote{body}} of the environment and therefore the inner levels % of the list and the \myenv*{keyans} environment. It is recommended to % set this key per level. % \end{important} % % \smallskip % % \begin{important}* % In the \myenv*{enumext*} and \myenv*{keyans*} environments this key % is executed after the \mykey{listparindent}, \mykey{parsep} and % \mykey{itemindent} keys within the \myenv{minipage} environment in % which the \emph{\enquote{item content}} is placed. % \end{important} % % \smallskip % % \keyexamp{after}{code}{not used} % Execute \mymarg{code} \emph{\enquote{after}} finishing the % environment. The \mymarg{code} must be passed between braces. % % \subsection{Keys for \texttt{start}, \texttt{series} and \texttt{resume}} % % \smallskip % % \keyexamp{start}{integer \textnormal{\textcolor{lightgray}{\textbar}} integer expression}{\mydim{1}} % Sets the \emph{start value} of the numbering on the current level. % The \mymarg{integer expression} must be passed between braces, internally is evaluated and pass % to the counter defined by \mykey{label} key on the current level, i.e. it is equivalent to enter % |start={\dimeval{100*\value{chapter}}| or |start={100*\value{chapter}}|. % % \smallskip % % \keyexamp{start\textcolor{MediumOrchid}{*}}{integer \textnormal{\textcolor{lightgray}{\textbar}} string}{not used} % Sets the \emph{start value} of the numbering on the current level. % Internally \mymeta{string} is converted and passed as value to the counter defined by % \mykey{label} key on the current level, i.e. it is equivalent to enter % |start=5|, |start=E| or |start=v|. % % \smallskip % % The following \mymeta{keys} are \emph{\enquote{only}} available for the % \myenv*{enumext*} environment and the \emph{\enquote{first level}} of % the \myenv*{enumext} environment and are ignored if set when nested % within each other. % % \keyexamp{series}{series name}{not used} % % \smallskip % % Stores the \emph{keys} of the \emph{optional argument} of the \emph{\enquote{first level}} % of the environment in which it is executed in \mymarg{series % name} which is used as an argument in the key \mykey{resume}. The \mymeta{keys} % stored in \mymarg{series name} are not cumulative and are overwritten % if the same \mymarg{series name} is used again. % % \smallskip % % \keyexamp{resume}{series name}{not used} % Sets the \emph{start value} and \emph{options} for the \emph{\enquote{first % level}} continuing the numbering of the environment in which the % \mykey{series}|=|\mymarg{series name} key was executed. If passed % \emph{without value} this will only set \emph{start value} continue the % numbering from the last environment in which \mykey{series}|=|\mymarg{series name} % or \mykey{resume}|=|\mymarg{series name} is not present and if the % \mykey{save-ans} key is active it will continue the numbering from the % last environment in which it was executed. The \emph{start value} can be % overwritten using \mykey{start} or \mykey{start*} keys. % % \smallskip % % \keyexamp*{resume\textcolor{MediumOrchid}{*}}{value forbidden}{not used} % Sets the \emph{start value} and \emph{options} for the % \emph{\enquote{first level}} continuing the numbering of the % environment in which the \mykey{series}|=|\mymarg{series name} or % \mykey{resume}|=|\mymarg{series name} keys are NOT present, if the % \mykey{save-ans} key is active it will continue the numbering from the % last environment in which it was executed. The \emph{start value} % can be overwritten using \mykey{start} or \mykey{start*} keys. % % \smallskip % % \begin{important}* % For security reasons the \mykey{series} key will never save in % \mymarg{series name} the keys \mykey{series}, \mykey{resume}, % \mykey{resume*}, \mykey{save-ans}, \mykey{save-key}, \mykey{start*} and \mykey{start}. % When using the key \mykey{resume}|=|\mymarg{series name} it will % have hierarchy in the \mymeta{keys} that are saved in \mymarg{series % name}, in order to establish the value of a \mymeta{key} already saved % in \mymarg{series name} it must be placed to the \emph{\enquote{right}} % of \mykey{resume}|=|\mymarg{series name}, the same thing happens with % the \mykey{resume*} key, the exception is the \mykey{save-ans} key % that must be placed on the \emph{\enquote{left}} if you want to start % the numbering with its value. % The \mykey{resume} key passed \emph{\enquote{without value}} must be % exactly \emph{\enquote{without value}}, i.e. \mykey{resume}|=| cannot % be used and if executed before \mykey{resume*} it will affect the % \emph{start value}. % \end{important} % % \subsection{Keys for \env{multicols}}\label{key:multi} % % \keyexamp{columns}{integer}{\mydim{1}} % % \smallskip % % Set the \emph{number of columns} to be used by the \myenv{multicols} % environment within the environment. The value must be a positive % integer less than or equal to \mydim{10}. % % \smallskip % % \keyexamp{columns-sep}{rigid length}{by level} % % \smallskip % % Set the \emph{space between} columns used by the \myenv{multicols} % environment within the environment. Internally sets the value of % \ics{columnsep}, by default its value is equal to the sum of the % values set in the keys \mykey{labelwidth} and \mykey{labelsep} of the % current level. % % \subsection{Keys for \env{minipage}}\label{key:mini} % % \keyexamp{mini-env}{rigid length}{not used} % % \smallskip % % Sets the \emph{width} of the \myenv{minipage} environment on % the \emph{\enquote{right side}}. This value added to the value set by % the \mykey{mini-sep} key to determines the \emph{width} of the % \myenv{minipage} environment on the \emph{\enquote{left side}}, taking % \ics{linewidth} as the maximum reference value. % % \smallskip % % \keyexamp{mini-sep}{rigid length}{\mydim{0.3333}em} % % \smallskip % % Sets the \emph{space between} the \myenv{minipage} environment on the % \emph{\enquote{left side}} and the \myenv{minipage} environment on % the \emph{\enquote{right side}}. This separation is applied together % with |\hfill|. % % \subsubsection{The command \cs[no-index]{miniright}} % % \vspace*{-1.0\baselineskip} % \begin{function}{\miniright} % \begin{syntax} % |\begin{enumext}[mini-env=|\mymarg{rigid length}|]| \mymeta[cf=gray]{item's before} |\item \miniright| \mymeta[cf=gray]{content} |\end{enumext}|\par % |\begin{enumext}[mini-env=|\mymarg{rigid length}|]| \mymeta[cf=gray]{item's before} |\item \miniright*|\mymeta[cf=gray]{content} |\end{enumext}| % \end{syntax} % \end{function} % % The \ics*{miniright} command close the \myenv{minipage} environment on % the \emph{\enquote{left side}} and opens the \myenv{minipage} environment % on the \emph{\enquote{right side}} by starting it with the |\centering| % command. It must be placed \emph{\enquote{after}} the last \ics*{item} % of the current environment and \emph{\enquote{before}} starting the % material to be placed on the \emph{\enquote{right side}}. % % \smallskip % % The \emph{starred argument} ‘|*|’ inhibits the use of |\centering| % command i.e. the usual \hologo{LaTeX} justification is maintained in % the \myenv{minipage} on the \emph{\enquote{right side}}. % % \smallskip % % \subsubsection{The key \texttt{mini-right}} % % In the \emph{horizontal list environments} \myenv*{enumext*} and \myenv*{keyans*} % it is not possible to use the \ics*{miniright} command and the \mykey{mini-right} % key must be used instead. % % \smallskip % % \keyexamp{mini-right}{content}{not used} % % \smallskip % % Set the \emph{content} for the drawing or tabular to be placed in the % \myenv{minipage} environment on the \emph{\enquote{right side}} by % starting it with |\centering|. The \mymarg{content} must be passed between braces. % % \smallskip % % \keyexamp{mini-right\textcolor{MediumOrchid}{*}}{content}{not used} % % \smallskip % % Same as above, but \emph{without} starting with |\centering|. % % \smallskip % % \section{The storage system}\label{sec:storage system} % % The entire mechanism for \emph{\enquote{storing content}} it is % activated according to \mykey{save-ans} key on the % \emph{\enquote{first level}} of \myenv*{enumext} or \myenv*{enumext*} % environments and it is ignored if they are established when they are % nested inside each other. Only when this \mymeta{key} is \emph{\enquote{active}} % the \ics*{anskey} command and the environments \myenv*{anskey*}, % \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} are available. % % \iffalse %<*example> % \fi \vspace*{-1\baselineskip} \begin{minipage}[t]{0.45\linewidth} \centering \begin{examplecode}[frame=none,mathescape=true] \begin{enumext}[save-ans=`\mymarg{store name}`] \item Text \anskey{answer} \item Text \begin{keyans} $\cdots$ \end{keyans} \end{enumext} \end{examplecode} \end{minipage}\hfill \begin{minipage}[t]{0.45\linewidth} \vspace{0pt}\centering \begin{examplecode}[frame=none,mathescape=true] \begin{enumext}[save-ans=`\mymarg{store name}`] \item Text \anskey{answer} \item Text \begin{keyanspic} $\cdots$ \end{keyanspic} \end{enumext} \end{examplecode} \end{minipage} % \iffalse % % \fi % % By executing the key \mykey{save-ans}|=|\mymarg{store name} the entire % \emph{\enquote{structure}} of the environment (excluding the \emph{first level}) % including the \emph{optional argument} passed to the inner levels or % the environment nested in it, along with the \mymeta{content} passed % to \ics*{anskey} or \myenv*{anskey*}, the current \mymeta{labels} for % \ics*{item*} and \ics*{anspic}|*| in the environments \myenv*{keyans}, % \myenv*{keyans*} and \myenv*{keyanspic} will be \emph{\enquote{stored}} % in a \emph{sequence} \mymarg{store name} and at the same time will be % \emph{\enquote{stored}} (without the \emph{\enquote{structure}} or % \emph{optional argument}) in a \emph{prop list} \mymarg{store name}. % % \smallskip % %^^A \begin{important}* % For security reasons the \emph{optional argument} of the inner levels % or the nested environment are \emph{filtered} by excluding all \mymeta{keys} % related to the \emph{\enquote{storage system}} (\S\ref{subsec:storage-keys}) % along with the keys \mykey{mini-env}, \mykey{mini-sep}, \mykey{mini-right}, % \mykey{mini-right*}, \mykey{series}, \mykey{resume} and \mykey{resume*} % when storing in \emph{sequence} \mymarg{store name} set by \mykey{save-ans} key. %^^A \end{important} % % \subsection{Keys for storage system}\label{subsec:storage-keys} % % The only \mymeta{keys} available for all levels of the \myenv*{enumext} % environment and the \myenv*{enumext*} environment are \mykey{no-store} % and \mykey{save-key}, the rest of the \mymeta{keys} described in this % section must be passed directly in the \emph{optional argument} of the % \emph{\enquote{first level}} of the environment in which the key % \mykey{save-ans} is executed. The key \mykey{save-ans} should NOT be passed % with the command \ics*{setenumext}. % % \smallskip % % \keyexamp{save-ans}{store name}{not set} % Sets the \emph{name} of the \emph{sequence} and \emph{prop list} in % which the \mymarg{contents} will be \emph{\enquote{stored}} by \ics*{anskey} % and \myenv*{anskey*} in \myenv*{enumext} and \myenv*{enumext*} % environments and the current \mymeta{labels} for \ics*{item*} and % \ics*{anspic}|*| in the environments \myenv*{keyans}, \myenv*{keyans*} % and \myenv*{keyanspic}. If the \emph{sequence} or \emph{prop list} % \mymarg{store name} does not exist, it will be created globally and % will not be \emph{overwritten} if the key is used again. % % \smallskip % % \keyexamp{save-key}{key list}{not set} % This key \emph{overrides} the default \emph{\enquote{stored keys}} of the % \emph{optional argument} of the inner levels or nested environment that will % be passed to the \emph{sequence}. The \mymeta{key list} passed to % this key ignores any \mymeta{keys} in the \emph{\enquote{stored % structure}} and must be passed between braces. For example, if we % execute at a second level: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=none,mathescape=true] \begin{enumext}[save-ans=`\mymarg{store name}`] \item Text \anskey{answer} \item Text \begin{enumext}[nosep, columns=2, save-key={columns=3}] $\cdots$ \end{enumext} \end{enumext} \end{examplecode} % \iffalse % % \fi % % The \emph{\enquote{stored keys}} by default in the \emph{sequence} % \mymarg{store name} would be |nosep, columns=2|, but using the key % \mykey{save-key}|={columns=3}| will overwrite and the % \emph{\enquote{stored key}} in the \emph{sequence} \mymarg{store name} % are only |columns=3| ignoring all the others. % % \smallskip % % \keyexamp{save-sep}{text symbol}{\{, \}} % Sets the \emph{text symbol} that will separate the current \mymeta{label} % to the \emph{optional argument} passed to the \ics*{item*} and \ics*{anspic}|*| % in the environments \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} % and storing them in the \emph{sequence} and \emph{prop list} \mymarg{store name} % set by \mykey{save-ans} key. % The \mymarg{text symbol} must always be passed between % braces, whitespace ‘\verb*+ +’ is preserved within the braces and only % affects the \emph{\enquote{stored content}} and not what is displayed % when using the \mykey{show-ans} or \mykey{show-pos} keys. % % \subsubsection{Keys for \texttt{label} and \texttt{ref}}\label{subsec:label-ref} % % \keyexamp{save-ref}{true \textnormal{\textcolor{lightgray}{\textbar}} false}{false} % Activates the \emph{\enquote{internal label and ref}} mechanism for % referencing \emph{\enquote{stored content}} in \emph{prop list} % \mymarg{store name} set by \mykey{save-ans} key. To reference the % location of the \emph{\enquote{stored content}} within the environment % you must use |\ref|\mymarg{store name \textnormal{\textcolor{red}{:}} position}, % where \mymeta{position} corresponds to the position occupied by the % \emph{\enquote{stored content}} in the \emph{prop list} \mymarg{store name} % returned by the \mykey{show-pos} key. For example |\ref{test:4}| will % return |3.(b)| which corresponds to the location of the \emph{\enquote{stored content}} % at position |4| in \emph{prop list} |test| within the environment in % which the key \mykey{save-ans}|=test| was set. % % \smallskip % % \keyexamp{mark-ref}{symbol}{\textbackslash{}\textreferencemark} % Sets the \emph{symbol} that will be displayed by the \ics*{printkeyans} % command only if the \mypkg{hyperref} package is detected and the % \mykey{save-ref} key are active. % This \emph{\enquote{symbol}} is used as a \emph{\enquote{link}} between the environment % in which the \mykey{save-ans} key was used and the place where the % command is executed. % % \subsubsection{Keys for \texttt{wrap} and \texttt{display}}\label{subsec:wrap-display} % % \keyexamp{wrap-ans}{code{} \space\usebox{\hashbox} more code}{\textbackslash{}fbox+\textbackslash{}parbox\{\#1\}} % Wraps the \emph{argument} passed to the \ics*{anskey} and the \emph{body} in \myenv*{anskey*} environment % referenced by |{#1}| when using the \mykey{show-ans} or \mykey{show-pos} keys. % The \mymarg{code} must be passed between braces and only affects the % \emph{argument} or \emph{body} and NOT the \emph{\enquote{stored % content}} in the \emph{sequence} and \emph{prop list} \mymarg{store % name} set by \mykey{save-ans} key. If this key is passed using % \ics*{setenumext} it is necessary to use double ‘|{##1}|’. % % \smallskip % % \keyexamp{wrap-opt}{code{} \space\usebox{\hashbox} more code}{[\{\#1\}]} % Wraps the \emph{optional argument} passed to the % \ics*{item*} and \ics*{anspic}|*| referenced by |{#1}| % in the \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} % environments when using the \mykey{show-ans} or \mykey{show-pos} keys. % The \mymarg{code} must be passed between braces % and only affects the current \emph{optional argument} and NOT the % \emph{\enquote{stored content}} in the \emph{sequence} and \emph{prop list} % \mymarg{store name} set by \mykey{save-ans} key. % If this key is passed using \ics*{setenumext} it is necessary to use double ‘|{##1}|’. % % \smallskip % % \keyexamp{show-ans}{true \textnormal{\textcolor{lightgray}{\textbar}} false}{false} % Displays the \emph{argument} passed to the \ics*{anskey}, the % \emph{body} for \myenv*{anskey*} environment, the \mymeta{label} % for \ics*{item*} and \ics*{anspic}|*| at the place where it is executed. % If the \emph{optional argument} is present in \ics*{item*} or \ics*{anspic}|*| it will % be shown using \mykey{wrap-opt} key. % % \smallskip % % \keyexamp{mark-ans}{symbol}{\textbackslash{}textasteriskcentered} % Sets the \emph{symbol} to be displayed in the left margin for % \ics*{anskey}, \myenv*{anskey*}, \ics*{item*} and \ics*{anspic}|*| in the place % where they are executed when using the key \mykey{show-ans}. % % \smallskip % % \keyexamp{mark-pos}{left \textnormal{\textcolor{lightgray}{\textbar}} right}{left} % Sets the \emph{aligned} of the symbol defined by \mykey{mark-ans} key. The % \emph{\enquote{symbol}} is aligned in a box with the same dimensions of the label box % defined by \mykey{labelwidth} key on the current level and separated by the value of the % \mykey{labelsep} key. % % \subsubsection{Keys for debug and checking} % % \keyexamp{show-pos}{true \textnormal{\textcolor{lightgray}{\textbar}} false}{false} % % \smallskip % % Displays the \emph{position} occupied by the \emph{\enquote{stored content}} by % \ics*{anskey}, \myenv*{anskey*}, \ics*{item*} and \ics*{anspic}|*| in the % \emph{prop list} \mymarg{store name} set by \mykey{save-ans} key. % This position is used by the \ics*{getkeyans} command and by the |\ref| % command if the \mykey{save-ref} key is active. % % \smallskip % % \keyexamp{check-ans}{true \textnormal{\textcolor{lightgray}{\textbar}} false}{false} % % \smallskip % % Enables the \emph{checking answer} mechanism displaying an % appropriate message on the terminal. This key works under the logic % that each \ics*{item} or \ics*{item*} that does not open an % inner level or nested environment contains \emph{\enquote{only one % answer}} or \emph{\enquote{only one execution}} of the \ics*{anskey} % or \myenv*{anskey*}. It is intended to be used in conjunction with the % \mykey{no-store} key. % % \smallskip % % \keyexamp*{no-store}{value forbidden}{not used} % % \smallskip % % This is a \emph{\enquote{switch-key}} that does not receive an argument % and disables the \emph{\enquote{stored structure}} in the \emph{sequence} % \mymarg{store name} set by \mykey{save-ans} key at the entire level % or a nested environment in which it runs. This key % is intended for use in internal levels or nested \myenv*{enumext} or % \myenv*{enumext*} environments in which % you want to use \myenv*{enumext} or \myenv*{enumext*} but \emph{\enquote{without}} using % the \ics*{anskey},\emph{\enquote{without}} use \myenv*{anskey*}, \emph{\enquote{without}} interfering with the % \mykey{check-ans} key and \emph{\enquote{without}} storing an unwanted % structure in the \emph{sequence} \mymarg{store name}. % % \subsection{The command \cs[no-index]{anskey}} % \label{sec:anskey} % % \vspace*{-\baselineskip} % % \begin{function}{\anskey} % \begin{syntax} % \cmdexamp{anskey}[keys]{content} % \end{syntax} % The command \ics*{anskey} takes a mandatory non empty argument \mymarg{content} % and \emph{\enquote{stores}} it in the \emph{sequence} and \emph{prop % list} \mymarg{store name} set by \mykey{save-ans} key. % By design the command cannot be nested or passed \emph{verbatim material} in the % argument and it is assumed that each \emph{numbered} |\item| or |\item*| within the % environment in which it is active it has a \emph{\enquote{single % execution}} of |\anskey| unless |\item| or |\item*| open a nested level % or use the \mykey{no-store} key. % % \smallskip % % If \mykey{save-ref} key are active and the % \mypkg{hyperref}\cite{hyperref} package is detected, |\hyperlink| and % |\hypertarget| will be used, otherwise the usual \emph{\enquote{label % and ref}} system provided by \hologo{LaTeX} will be used. % \end{function} % % \smallskip % % The \ics*{anskey} command is available for all levels of the % \myenv*{enumext} environment and the \myenv*{enumext*} environment, but % is disabled for the \myenv*{keyans}, \myenv*{keyans*} and % \myenv*{keyanspic} environments. % % \subsubsection{Keys for \cs[no-index]{anskey}} % % By default the \mymarg{content} passed to |\anskey| when % \emph{\enquote{storing}} in the \emph{sequence} \mymarg{store name} has % the form |\item| \mymeta{content}, the following \mymeta{keys} allow % modifying the way in which it is \emph{\enquote{stored}} in the % \emph{sequence}. % % \smallskip % % \keyexampcmd*{break-col}{value forbidden}{not used} % % \smallskip % % Stores \mymarg{content} in the \emph{sequence} \mymarg{store name} of % the form \ics{columnbreak} |\item| \mymeta{content}. % % \smallskip % % \keyexampcmd{item-join}{columns}{not set} % % \smallskip % % Set the \emph{number of columns} to be used for |\item|\myparg{columns} and stores \mymarg{content} in the \emph{sequence} % \mymarg{store name} of the form |\item|\myparg{columns} \mymeta{content}. % % \smallskip % % \keyexampcmd*{item-star}{value forbidden}{not used} % % \smallskip % % Stores \mymarg{content} in the \emph{sequence} \mymarg{store name} of % the form |\item*| \mymeta{content}. % % \keyexampcmd{item-sym\textcolor{MediumOrchid}{*}}{symbol}{not set} % % \smallskip % % Sets the \emph{symbol} for |\item*| when using the key % \mykeycmd{item-star} and stores \mymarg{content} in the \emph{sequence} % \mymarg{store name} of the form |\item*|\myoarg{symbol} \mymeta{content}. % The \emph{symbol} can be in text or math mode, for example % \mykeycmd{item-sym*}|={$\ast$}| stores |\item*||[$\ast$]| \mymeta{content}. % % \smallskip % % \keyexampcmd{item-pos\textcolor{MediumOrchid}{*}}{rigid length}{not set} % Sets the \emph{offset} for |\item*| when using the keys % \mykeycmd{item-star} and \mykeycmd{item-sym*} and stores \mymarg{content} in the \emph{sequence} % \mymarg{store name} of the form |\item*|\myoarg{symbol}\myoarg{offset} \mymeta{content}. % % \subsubsection*{Example} % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \begin{enumext}[save-ans=test,show-ans=true] \item* Text containing our instructions or questions. `\ics*{anskey}\mymarg{first answer}` \item Text containing our instructions or questions. \begin{enumext} \item Question.`\ics*{anskey}\mymarg{second answer}` \end{enumext} \item Text containing our instructions or questions. `\ics*{anskey}\mymarg{third answer}` \item Text containing our instructions or questions. `\ics*{anskey}\mymarg{fourth answer}` \end{enumext} \end{examplecode} % \iffalse % % \fi % % \begin{enumext}[save-ans=test,show-ans=true,columns=2,nosep] % \item* Text containing our instructions or questions.\anskey{first answer} % \item Text containing our instructions or questions. % \begin{enumext} % \item Question.\anskey{second answer} % \end{enumext} % \item Text containing our instructions or questions. \anskey{third answer} % \item Text containing our instructions or questions. \anskey{fourth answer} % \end{enumext} % % \subsection{The environment \env{anskey*}} % % \vspace*{-\baselineskip} % % \begin{function}{anskey*} % \begin{syntax} % |\begin{anskey*}|\myoarg{key \textnormal{\textcolor{gray}{=}} val} \mymeta{body content} |\end{anskey*}| % \end{syntax} % The environment \myenv*{anskey*} takes a mandatory \mymarg{body content} % and \emph{\enquote{stores it}} in the \emph{sequence} and \emph{prop % list} \mymarg{store name} set by \mykey{save-ans} key. If \mykey{save-ref} % key are active and the \mypkg{hyperref}\cite{hyperref} package is % detected |\hyperlink| and |\hypertarget| will be used, otherwise the % usual \emph{\enquote{label and ref}} system provided by \hologo{LaTeX} will be used. % By design the environment cannot be nested but full supports \emph{\enquote{verbatim material}} in the % body and it is assumed that each numbered|\item| or |\item*| within the % environment in which it is active it has a \emph{\enquote{single % execution}} unless |\item| or |\item*| open a nested level % or use the \mykey{no-store} key. % \end{function} % % The \myenv*{anskey*} environment is implemented using the \mypkg{scontents} % package, for the correct operation |\begin{anskey*}| and |\end{anskey*}| % must be in different lines, all \mymeta{keys} must be passed separated by % commas and \enquote{without separation} of the start of the environment. % Comments \enquote{\textcolor{gray}{\%}} or \enquote{any character} % after |\begin{anskey*}| or \myoarg{key \textnormal{\textcolor{gray}{=}} val} % on the same line are NOT supported, the package \mypkg{scontents} will return an % \enquote{error} message if this happens. In a similar way comments % \enquote{\textcolor{gray}{\%}} or \enquote{any character} after % % |\end{anskey*}| on the same line the package \mypkg{scontents} will % return a \enquote{warning} message. % % \subsubsection{Keys for \texttt{anskey*}} % % The \myenv*{anskey*} environment uses the same \mymeta{keys} as the % \ics*{anskey} command next to the keys inherited from package \mypkg{scontents}. % The environment is available for all levels of the % \myenv*{enumext} environment and the \myenv*{enumext*} environment, but % it is disabled for the \myenv*{keyans}, \myenv*{keyans*} and % \myenv*{keyanspic} environments. % % \smallskip % % \keyexampenv{write-env}{file.ext}{not used} % % \smallskip % % Sets the name of the \mymeta{external file} in which the \mymeta{contents} of % the environment will be written. The \mymeta{file.ext} will be created % in the working directory, relative or absolute paths are not supported. If \mymeta{file.ext} % does not exist, it will be created or overwritten if the \mykey{overwrite} key is used. % % \smallskip % % \keyexampenv{overwrite}{true \textnormal{\textcolor{lightgray}{\textbar}} false}{false} % Sets whether the \mymeta{file.ext} generated by \mykey{write-env} % from the \myenv*{anskey*} environment will be rewritten. % % \smallskip % % \keyexampenv{force-eol}{true \textnormal{\textcolor{lightgray}{\textbar}} false}{false} % % \smallskip % % Sets if the \emph{end of line} for the \mymeta{stored content} is hidden or not. % This key is necessary only if the last line is the closing of some % environment defined by the \mypkg{fancyvrb} package as |\end{|\myenv{Verbatim}|}| % or another environment that does not support a comments \enquote{\ttfamily\textcolor{gray}{\%}} % after closing |\end{|\myenv{Verbatim}|}%|. % % \smallskip % % \begin{important}* % For security reasons the keys |store-env|, |print-env| and |write-out| % they have been left disabled. It is recommended that you review the % \mypkg{scontents}\cite{scontents} documentation to understand how % the keys described here work. % \end{important} % % \subsubsection*{Example} % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \begin{enumext}[save-ans=test,show-pos=true,start=5] \item* Text containing our instructions or questions. \begin{anskey*}[item-star] `\mymeta{first answer}` \end{anskey*} \item Text containing our instructions or questions. \begin{enumext} \item Question. \begin{anskey*} `\mymeta{second answer}` \end{anskey*} \end{enumext} \item Text containing our instructions or questions. \begin{anskey*} `\mymeta{third answer}` \end{anskey*} \item Text containing our instructions or questions. \begin{anskey*} `\mymeta{fourth answer}` \end{anskey*} \end{enumext} \end{examplecode} % \iffalse % % \fi % % \begin{enumext}[save-ans=test,show-pos=true,columns=2,nosep,start=5] % \item* Text containing our instructions or questions. % \begin{anskey*} % First answer with \verb+verbatim+ % \end{anskey*} % \item Text containing our instructions or questions. % \begin{enumext} % \item Question.\anskey{second answer} % \end{enumext} % \item Text containing our instructions or questions. \anskey{third answer} % \item Text containing our instructions or questions. \anskey{fourth answer} % \end{enumext} % % \subsection[The environment \texttt{keyans}]{The environments \env{keyans} and \env{keyans*}} % % \vspace*{-\baselineskip} % % \begin{function}{keyans,keyans*} % \begin{syntax} % |\begin{keyans}|\myoarg{key \textnormal{\textcolor{gray}{=}} val} \ics*{item} \ics*{item}\myoarg{custom} \ics*{item*} \ics*{item*}\myoarg{content} |\end{keyans}|\par % |\begin{keyans*}|\myoarg{key \textnormal{\textcolor{gray}{=}} val} \ics*{item} \ics*{item}\myoarg{custom} \ics*{item*} \ics*{item*}\myoarg{content} |\end{keyans*}| % \end{syntax} % The \myenv*{keyans} and \myenv*{keyans*} environments are % \emph{\enquote{enumerated list}} environments designed for % \emph{\enquote{multiple choice}} questions activated by the \mykey{save-ans} key. % This environments can NOT be nested and must always be at the % \emph{\enquote{first level}} of the \myenv*{enumext} environment, the % commands \ics*{item} and \ics*{item}\myoarg{custom} work in the usual % and the command |\item|\myparg{columns} is available for the \myenv*{keyans*} environment. % % \smallskip % % \begin{important}* % The behavior of |\item*| in \myenv*{keyans} and \myenv*{keyans*} environments % is NOT the same as in the \myenv*{enumext} or \myenv*{enumext*} environments. % \end{important} % \end{function} % % \iffalse %<*example> % \fi \vspace*{-1\baselineskip} \begin{minipage}[t]{0.45\linewidth} \begin{examplecode}[frame=none] \begin{enumext}[save-ans=test] \item `\mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \begin{keyans}`\myoarg{key \textnormal{\textcolor{gray}{=}} val}` \item `\mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \item `\myoarg{custom} \mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \item* `\mymeta[type=tt,ac=lightgray,cf=gray]{item content}` `\ics*{item*}\myoarg{content} \mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \end{keyans} \end{enumext} \end{examplecode} \end{minipage} \hfill \begin{minipage}[t]{0.45\linewidth} \begin{examplecode}[frame=none] \begin{enumext}[save-ans=test] \item `\mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \begin{keyans*}`\myoarg{key \textnormal{\textcolor{gray}{=}} val}` \item `\mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \item `\myoarg{custom} \mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \item* `\mymeta[type=tt,ac=lightgray,cf=gray]{item content}` `\ics*{item*}\myoarg{content} \mymeta[type=tt,ac=lightgray,cf=gray]{item content}` \end{keyans*} \end{enumext} \end{examplecode} \end{minipage} % \iffalse % % \fi % % The \mymeta{keys} set in the \emph{optional argument} of the environment are the same % (almost) as those of the \myenv*{enumext} and \myenv*{enumext*} % environments and have \emph{higher precedence} than those set by % \ics*{setenumext}\myoarg{keyans}\mymarg{key \textnormal{\textcolor{gray}{=}} val} or % \ics*{setenumext}\myoarg{keyans\textnormal{\textcolor{MediumOrchid}{\texttt{*}}}}\mymarg{key \textnormal{\textcolor{gray}{=}} val}. % If the \emph{optional argument} is not passed or the \mymeta{keys} % are not set by \ics*{setenumext}, the default values will be the same % as the \emph{\enquote{second level}} of the \myenv*{enumext} environment % with the difference in the \mymeta{label} which will be set to \mykey{label}=\ilabel{Alph*)}. % % \subsubsection[The \texttt{\textbackslash item*} in \texttt{keyans}]{The \cs[no-index]{item*} in \texttt{keyans} and \texttt{keyans*}} % % \vspace*{-\baselineskip} % % \begin{function}{\item*} % \begin{syntax} % \ics*{item*} % \ics*{item*}\myoarg{content} % \end{syntax} % The \ics*{item*} and \ics*{item*}\myoarg{content} command \emph{\enquote{store}} % the current \mymeta{label} set by \mykey{label} key next to the \emph{optional argument} \mymeta{content} % in \emph{sequence} and \emph{prop list} \mymarg{store name} set by % \mykey{save-ans} key in the \emph{\enquote{first level}} of the % \myenv*{enumext} or \myenv*{enumext*} environments. % \end{function} % % The \emph{starred argument} ‘|*|’ cannot be separated by spaces ‘\verb*| |’ % from the command, i.e. \ics*{item*} and the \emph{optional argument} % does \enquote{NOT} support \emph{verbatim content}. By design it is % assumed that the |\item*| will only appear \emph{\enquote{once}} % within the environment. % % \subsubsection*{Example} % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \begin{enumext}[save-ans=test,columns=2,show-ans=true] \item Text containing a question. \begin{keyans*}[nosep,columns=2] \item Choice \item* Correct choice \item Choice \item Choice \item Choice \end{keyans*} \item Text containing a question and image. \begin{keyans}[nosep,mini-env={0.4\linewidth}] \item Choice \item Choice \item Choice \item Choice `\ics*{item*}\myoarg{note}` Correct choice \miniright \includegraphics[scale=0.25]{example-image-a} Some text \end{keyans} \end{enumext} \end{examplecode} % \iffalse % % \fi % % \begin{enumext}[save-ans=test,show-ans=true,columns=2,nosep] % \item Text containing a question. % % \begin{keyans*}[nosep,columns=2] % \item Choice % \item* Correct choice % \item Choice % \item Choice % \item Choice % \end{keyans*} % % \item Text containing a question and image. % % \begin{keyans}[nosep,mini-env={0.4\linewidth}] % \item Choice % \item Choice % \item Choice % \item Choice % \item*[note] Correct choice % \miniright % \includegraphics[scale=0.15]{example-image-a} % % Some text % \end{keyans} % \end{enumext} % % \subsection{The environment \texttt{keyanspic}} % % \vspace*{-\baselineskip} % % \begin{function}{keyanspic} % \begin{syntax} % |\begin{keyanspic}|\myoarg{key \textnormal{\textcolor{gray}{=}} val} \ics*{anspic}|*|\myoarg{content}\mymarg{drawing or tabular} |\end{keyanspic}| % \end{syntax} % The \myenv*{keyanspic} environment is an \emph{\enquote{enumerated % list}} environment activated by the \mykey{save-ans} key that has the % same configuration for \emph{\enquote{spacing}} and \mymeta{label} % as the \myenv*{keyans} environment that uses the |\anspic| command % instead of |\item|. It is intended for placing \emph{drawings or tabular} % with \mymeta{label} centered \emph{above} or \emph{below} in a \emph{single line} % or \emph{upper and lower} layout style. % % \smallskip % % When the \myenv*{keyanspic} environment is used \emph{without keys} % the \mymeta{labels} are centered \emph{below} the \emph{drawings % or tabular} in a \emph{single line} layout style. % \end{function} % % A representation of the output can be seen in the figure \ref{fig:keyanspicdoc}. % % \begin{figure}[ht] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % % space above % \draw[color=white] (7.0,6.10) rectangle (17.5,6.5) node[pos=.5,text=black]% % { \textcolor{lightgray}{\texttt{number of drawings or tabular upper}} }; % \draw[color=white] (7.0,4.5) rectangle (17.5,4.9) node[pos=.5,text=black]% % { \textcolor{optcolor}{\texttt{layout-sep}} }; %%%[+itemsep] % \draw[color=white] (7.0,2.9) rectangle (17.5,3.3) node[pos=.5,text=black]% % { \textcolor{lightgray}{\texttt{number of drawings or tabular lower}} }; % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=optcolor]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (17.5,6.85) node[pos=.5,text=black]% % {\begin{tabular}{c} % \textcolor{blue}{\emph{item text above the keyanspic environment}} % \end{tabular}};% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.25) rectangle (10.5,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{above one} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,4.9) rectangle (10.5,5.25) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (10.5,5.25) rectangle (14,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{above two} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (10.5,4.9) rectangle (14,5.25) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (14,5.25) rectangle (17.5,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{above three} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (14,4.9) rectangle (17.5,5.25) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,3.65) rectangle (12.25,4.5) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{below one} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,3.3) rectangle (12.25,3.65) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (12.25,3.65) rectangle (17.5,4.5) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{below two} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (12.25,3.3) rectangle (17.5,3.65) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,2.55) rectangle (5.0,2.9);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,2.55) rectangle (7.0,2.9);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,2.55) rectangle (17.5,2.9) node[pos=.5,text=black]% % {\begin{tabular}{c} % \textcolor{blue}{\emph{item text below the keyanspic environment}} % \end{tabular}};% item width % \end{tikzpicture} % \caption{Representation of the \myenv*{keyanspic} environment with \mykey{layout-sty}=\mymarg{3, 2} in \mypkg*{enumext}.} % \label{fig:keyanspicdoc} % \end{figure} % % \smallskip % % This environment cannot be nested and must always be at the % \emph{\enquote{first level}} of the \myenv*{enumext} environment, the % \ics*{item} command is disabled and keys cannot be set using % |\setenumext|. % % \subsubsection{Keys for \texttt{keyanspic}} % % \keyexamp{label-pos}{above \textnormal{\textcolor{lightgray}{\textbar}} below}{below} % % \smallskip % % Set the \emph{position} of \mymeta{label} to be centered % \enquote{above} or \enquote{below} \emph{drawings} or \emph{tabular} % when the |\anspic| command is executed. % % \smallskip % % \keyexamp{label-sep}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{internal adjustment} % % \smallskip % % Set the \emph{vertical spacing} between the \mymeta{label} centered % \enquote{above} or \enquote{below} and \emph{drawings} or \emph{tabular} % when running the |\anspic| command. % % \keyexamp{layout-sty}{n° upper \textnormal{\textcolor{gray}{,}} n° lower}{not set} % % \smallskip % % Set the \emph{number} of \emph{drawings} or \emph{tabular} that will be % distributed \enquote{upper} and \enquote{lower} within the environment % when executing the |\anspic| command. The value must be passed in braces % and if not set or the \mymeta{nº lower} is omitted the \emph{drawings} % or \emph{tabular} will be put on a \emph{single line}. % % \smallskip % % \keyexamp{layout-sep}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{adjusted parsep from keyans} % % \smallskip % % Set the \emph{vertical separation} between the number of % \emph{drawings} or \emph{tabular} placed at the \enquote{upper} and % \enquote{lower} within the environment when executing the |\anspic| % command. Internally adjusts the \mykey{parsep} value taken from the % \myenv*{keyans} environment. % % \smallskip % % \keyexamp{layout-top}{rubber length \textnormal{\textcolor{lightgray}{\textbar}} rigid length}{adjusted topsep from keyans} % % \smallskip % % Set the \emph{vertical space} added to both the top and bottom of the environment. % Internally adjust the value of \mykey{topsep} taken from \myenv*{keyans} environment. % % \subsubsection{The command \cs[no-index]{anspic}} % % \vspace*{-\baselineskip} % % \begin{function}{\anspic} % \begin{syntax} % \cmdexamp{anspic}{drawing or tabular} % \cmdexamp[*]{anspic}[content]{drawing or tabular} % \end{syntax} % The \ics*{anspic} command take three arguments, the \emph{starred % argument} ‘|*|’ store the current \mymeta{label} next to the % \emph{optional argument} \mymeta{content} in \emph{sequence} and % \emph{prop list} \mymarg{store name} set by \mykey{save-ans} key. % \end{function} % % \smallskip % % The \emph{starred argument} ‘|*|’ cannot be separated by spaces ‘\verb*| |’ % from the command, i.e. \ics*{anspic}|*| and the \emph{optional argument} % does \enquote{NOT} support \emph{verbatim content}. By design it % is assumed that the \emph{starred argument} ‘|*|’ will only % appear \emph{\enquote{once}} within the environment. % % \subsubsection*{Example} % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \begin{enumext}[save-ans=test,show-ans,nosep] \item Question with images and labels below. \begin{keyanspic}[layout-sty={3,2}] \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-b}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic*[note]{\includegraphics[scale=0.15]{example-image-a}} \end{keyanspic} \item Question with images and labels above. \begin{keyanspic}[label-pos=above, layout-sty={3,2},layout-sep=0.25cm] \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-b}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic*[note]{\includegraphics[scale=0.15]{example-image-a}} \end{keyanspic} \item Question with images and labels below on a single line. \begin{keyanspic} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-b}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic*[note]{\includegraphics[scale=0.15]{example-image-a}} \end{keyanspic} \end{enumext} \end{examplecode} % \iffalse % % \fi % % \begin{enumext}[save-ans=test,show-ans=true,nosep, before={\setenumext[keyans]{nosep,parsep=5mm}}] % \item Question with images and labels below. % \begin{keyanspic}[layout-sty={3,2}] % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-b}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic*[note]{\includegraphics[scale=0.15]{example-image-a}} % \end{keyanspic} % \item Question with images and labels above. % \begin{keyanspic}[label-pos=above, layout-sty={3,2},layout-sep=0.25cm] % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-b}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic*[note]{\includegraphics[scale=0.15]{example-image-a}} % \end{keyanspic} % \item Question with images and labels below on a single line. % \begin{keyanspic} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-b}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic*[note]{\includegraphics[scale=0.15]{example-image-a}} % \end{keyanspic} % \end{enumext} % % \smallskip % % \begin{important} % Remember to pass the |alt=|\mymarg{description} key to the |\includegraphics| % command when creating a \emph{tagged} PDF. % \end{important} % % \subsection{Printing stored content} % % \subsubsection{The command \cs[no-index]{getkeyans}} % \label{sec:getkeyans} % % \vspace*{-10pt} % % \begin{function}{\getkeyans} % \begin{syntax} % \cmdexamp{getkeyans}{store name \textnormal{\textcolor{red}{:}} position} % \end{syntax} % The command \ics*{getkeyans} prints the \emph{\enquote{stored content}} % in \emph{prop list} \mymarg{store name} defined by % \mykey{save-ans} key in the \mymeta{position} returned by the % \mykey{show-pos} key. % The \emph{\enquote{stored content}} can only be accessed \emph{after} % it is stored, if \mymarg{store name} does not exist the command % will return an error. % \end{function} % % \smallskip % % The form taken by the argument \mymarg{store name \textnormal{\textcolor{red}{:}} position} % is the same as that used to generate the \emph{\enquote{internal % label and ref}} system when \mykey{save-ref} key are active, so to % refer to a \emph{\enquote{stored content}}. For example % |\getkeyans{test:4}| will return the \emph{\enquote{stored content}} % at position |4| of the environment in which the key |save-ans=test| % was set. % % \subsubsection{The command \cs{foreachkeyans}}\label{sec:foreachkeyans} % % \vspace*{-10pt} % % \begin{function}{\foreachkeyans} % \begin{syntax} % \cmdexamp{foreachkeyans}[key \textnormal{\textcolor{gray}{=}} val]{store name} % \end{syntax} % \end{function} % % The command \ics*{foreachkeyans} goes through and executes the command |\getkeyans| % on the contents in \emph{prop list} \mymarg{store name}. If you pass without options run % |\getkeyans| on all contents in \emph{prop list} \mymarg{store name}. % % \subsubsection*{Options for command} % \label{sec:optcmdforeach} % % \keyexampcmd{sep}{code}{\{; \}}[foreachkeyans] % % \smallskip % % Establishes the \emph{separation} between \emph{\enquote{each}} \mymarg{content} stored in \emph{prop list} \mymarg{store name}. % For example, you can use \mykeycmd[foreachkeyans]{sep}|={\\[10pt]}| for vertical separation of stored % contents. % % \smallskip % % \keyexampcmd{step}{integer}{\mydim{1}}[foreachkeyans] % % \smallskip % % Sets the \emph{step} (increment) applied to the value set by key \mykeycmd[foreachkeyans]{start} % for \emph{\enquote{each}} \mymarg{content} stored in \emph{prop list} \mymarg{store name}. The value must be a % \mymeta{positive integer}. % % \keyexampcmd{start}{integer}{\mydim{1}}[foreachkeyans] % % \smallskip % % Sets the \emph{position} of the \emph{prop list} \mymarg{store name} from which execution % will start. The value must be a \mymeta{positive integer}. % % \keyexampcmd{stop}{integer}{\mydim{0}}[foreachkeyans] % % \smallskip % % Sets the \emph{position} of the \emph{prop list} \mymarg{store name} from which execution % will finish. The value must be a \mymeta{positive integer}. % % \keyexampcmd{before}{code}{empty}[foreachkeyans] % % \smallskip % % Sets the \mymarg{code} that will be executed \mymeta{before} each \mymarg{content} stored % in \emph{prop list} \mymarg{store name}. The \mymarg[type=tt]{code} must be passed between braces. % % \keyexampcmd{after}{code}{empty}[foreachkeyans] % % \smallskip % % Sets the \mymarg{code} that will be executed \mymeta{after} each \mymarg{content} stored % in \emph{prop list} \mymarg{store name}. The \mymarg{code} must be passed between braces. % % \keyexampcmd{wrapper}{code{} \space\usebox{\hashbox} more code}{empty}[foreachkeyans] % % \smallskip % % Wraps the \mymarg{content} stored in \emph{prop list} \mymarg{store name} referenced by |{#1}|. % The \mymarg{code} must be passed between braces. For example % |\foreachkeyans[wrapper={\makebox[1em][l]{#1}}]|\mymarg{store name}. % % \subsubsection{The command \cs[no-index]{printkeyans}}\label{sec:printkeyans} % % \vspace*{-10pt} % % \begin{function}{\printkeyans} % \begin{syntax} % \cmdexamp{printkeyans}{store name} % \cmdexamp{printkeyans}[keys]{store name} % \cmdexamp[*]{printkeyans}[keys]{store name} % \end{syntax} % The command \ics*{printkeyans} prints \emph{\enquote{all stored content}} % in \emph{sequence} \mymarg{store name} defined by \mykey{save-ans} % key placing this inside the \myenv*{enumext} or \myenv*{enumext*} % environment if the \emph{starred argument} ‘|*|’ is used. % % \smallskip % % The \emph{\enquote{stored content}} can only be accessed \emph{after} it is % stored in the \emph{sequence}, if \mymarg{store name} does not exist the % command will return an error. % \end{function} % % \smallskip % % The \emph{optional argument} allows managing the \mymeta{keys} in the % \emph{\enquote{first level}} of the environment in which the % \emph{\enquote{stored content}} of the \emph{sequence} \mymarg{store % name} will be printed, if the \emph{starred argument} ‘|*|’ is used it will be % \myenv*{enumext*} otherwise \myenv*{enumext}. % % \smallskip % % The default values ​​for the \emph{\enquote{first level}} are the % same as the default values for the \myenv*{enumext} and \myenv*{enumext*} % environments along with the keys |nosep,first=\small,font=\small| and |columns=2|. % For the inner levels of the environment \myenv*{enumext} saved in the % \emph{sequence} \mymarg{store name} the default values ​​are the same % as those established for the second, third and fourth levels plus the % keys |nosep,first=\small,font=\small|. If the environment \myenv*{enumext*} % is saved within the \emph{sequence} \mymarg{store name} it will have % the same default values plus the keys |nosep,first=\small, font=\small|. % % \smallskip % % Since the command encapsulates by default the \myenv*{enumext} % environment or the \myenv*{enumext*} environment, we must take some % considerations: % %\begin{itemize}[topsep=0pt] % \item If we execute |\printkeyans*|\mymarg{store name} and the \emph{sequence} % \mymarg{store name} already contains any \myenv*{enumext*} environment % an error will be returned as we cannot nest. % % \item If we execute |\printkeyans*|\mymarg{store name} and the \emph{sequence} % \mymarg{store name} contains any \myenv*{enumext} environments, they % will start with the \mymeta{keys} set for the first level unless they % are set in the \emph{optional argument} or \mykey{save-key} is used to modify it. % % \item If we execute |\printkeyans|\mymarg{store name} and the \emph{sequence} % \mymarg{store name} contains any environment \myenv*{enumext*}, they % will start with the \mymeta{keys} set by default unless they are set % in the \emph{optional argument} or \mykey{save-key} is used to modify it. %\end{itemize} % % The default values ​​for the \emph{\enquote{first level}} of |\printkeyans| commands and % |\printkeyans*| are established using \ics*{setenumext}\myoarg{print \textnormal{\textcolor{gray}{,}} \textcolor{MediumOrchid}{1}}\mymarg{keys} and % \ics*{setenumext}\myoarg{print\textnormal{\textcolor{MediumOrchid}{\texttt{*}}}}\mymarg{keys}. % % \smallskip % % If we need to set the \mymeta{keys} for the environment % \myenv*{enumext} \enquote{saved} in the \emph{sequence} \mymarg{store % name} we will use \ics*{setenumext}\myoarg{print % \textnormal{\textcolor{gray}{,}} level}\mymarg{keys} and if we need to % set the \mymeta{keys} for the environment \myenv*{enumext*} % \enquote{saved} in the \emph{sequence} \mymarg{store name} we will use % \ics*{setenumext}\myoarg{print \textnormal{\textcolor{gray}{,}} % \textnormal{\textcolor{MediumOrchid}{\texttt{*}}}}\mymarg{keys}. % % \subsubsection*{Example} % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \begin{enumext}[save-ans=sample,columns=1,show-pos=true,nosep,save-ref=true] \item Factor $3x+3y+3z$. \anskey{$3(x+y+z)$} \item True False \begin{enumext}[nosep] \item \LaTeX2e\ is cool? \anskey{Very True!} \end{enumext} \item Related to Linux \begin{enumext}[nosep] \item You use linux? \anskey{Yes} \item Rate the following package and class \begin{enumext}[nosep] \item \texttt{xsim} \anskey{very good} \item \texttt{exsheets} \anskey{obsolete} \end{enumext} \end{enumext} \end{enumext} The answer to \ref{sample:4} is \getkeyans{sample:4} and the answers to all the worksheets are as follows: \printkeyans{sample} \end{examplecode} % \iffalse % % \fi % % \begin{enumext}[save-ans=sampleXX,columns=1,show-pos=true,nosep,save-ref=true] % \item Factor $3x+3y+3z$. \anskey{$3(x+y+z)$} % \item True False % \begin{enumext}[nosep] % \item \LaTeX2e\ is cool? \anskey{Very True!} % \end{enumext} % \item Related to Linux % \begin{enumext}[nosep] % \item You use linux? \anskey{Yes} % \item Rate the following package and class % \begin{enumext}[nosep] % \item \texttt{xsim} \anskey{very good} % \item \texttt{exsheets} \anskey{obsolete} % \end{enumext} % \end{enumext} % \end{enumext} % % \medskip % % The answer to \ref{sampleXX:4} is \getkeyans{sampleXX:4} and the answers to % all the worksheets are as follows: % % \medskip % % \printkeyans[columns=1]{sampleXX} % % \section{Full examples} % % Here I will leave as an example some adaptations questions taken from \href{https://tex.stackexchange.com}{TeX-SX}. % The examples are attached to this documentation and can be extracted % from your PDF viewer or from the command line by running: % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] $ pdfdetach -saveall enumext.pdf \end{examplecode} % \iffalse % % \fi % and then you can use the excellent \arara\footnote{The cool \TeX\ automation tool: % \url{https://www.ctan.org/pkg/arara}} tool to compile them. % % \subsubsection*{Example 1} % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-exa-1.tex} % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log] } \documentclass{article} \usepackage{siunitx,amssymb,enumext} \sisetup{output-decimal-marker={,}} \DeclareSIUnit{\angstrom}{\textup{\AA}} \pagestyle{empty} \begin{document} \setenumext[keyans]{label=\Alph*,labelsep=10pt,font=\small,nosep,itemsep=2pt,wrap-label={\fbox{\makebox[\height]{##1}}}} \begin{enumext}[mode-box,columns=2,columns-sep=1cm,save-ans=sabastiano] \item La velocità di \qty{1,00e2}{m/s} espressa in \unit{km/h} è: \begin{keyans} \item \qty{36}{km/h}. \item* \qty{360}{km/h}. \item \qty{27,8}{km/h}. \item \qty{3,60e8}{km/h}. \end{keyans} \item In fisica nucleare si usa l'angstrom (simbolo: $\qty{1}{\angstrom} = \qty{1e-10}{m}$) e il fermi o femtometro ($\qty{1}{fm} = \qty{1e-15}{m}$). Qual è la relazione tra queste due unità di misura? \begin{keyans} \item* $\qty{1}{\angstrom}=\qty{1e5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-15}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e3}{fm}$. \end{keyans} \item La velocità di \qty{1,00e2}{m/s} espressa in \unit{km/h} è: \begin{keyans} \item \qty{36}{km/h}. \item* \qty{360}{km/h}. \item \qty{27,8}{km/h}. \item \qty{3,60e8}{km/h}. \end{keyans} \item In fisica nucleare si usa l'angstrom (simbolo: $\qty{1}{\angstrom} = \qty{1e-10}{m}$) e il fermi o femtometro ($\qty{1}{fm} = \qty{1e-15}{m}$). Qual è la relazione tra queste due unità di misura? \begin{keyans} \item* $\qty{1}{\angstrom}=\qty{1e5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-15}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e3}{fm}$. \end{keyans} \end{enumext} \printkeyans[columns=4]{sabastiano} \end{document} \end{filecontents*} % \iffalse % % \fi % % Adapted from the response given by Enrico Gregorio in \href{https://tex.stackexchange.com/q/461730/7832}{Squares for answer choice options and perfect alignment to mathematical answers} % \textattachfile[color=red,print=false]{enumext-exa-1.tex}{\faFile*[regular]}. % % \setenumext[keyans]{label=\Alph*,font=\small,nosep,wrap-label={\fbox{\makebox[\height]{##1}}}} % \begin{enumext}[columns=2,save-ans=sabastiano,itemsep=0pt, topsep=0pt,below*={8pt}] % \item La velocità di \SI{1,00e2}{m/s} espressa in \si{km/h} è: % % \begin{keyans} % \item \SI{36}{km/h}. % \item* \SI{360}{km/h}. % \item \SI{27,8}{km/h}. % \item \SI{3,60e8}{km/h}. % \end{keyans} % % \item In fisica nucleare si usa l'angstrom (simbolo: % $\SI{1}{\angstrom} = \SI{1e-10}{m}$) e il fermi o femtometro % ($\SI{1}{fm} = \SI{1e-15}{m}$). Qual è la relazione tra queste due % unità di misura? % \begin{keyans} % \item* $\SI{1}{\angstrom}=\SI{1e5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-15}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e3}{fm}$. % \end{keyans} % % \item La velocità di \SI{1,00e2}{m/s} espressa in \si{km/h} è: % % \begin{keyans} % \item \SI{36}{km/h}. % \item* \SI{360}{km/h}. % \item \SI{27,8}{km/h}. % \item \SI{3,60e8}{km/h}. % \end{keyans} % % \item In fisica nucleare si usa l'angstrom (simbolo: % $\SI{1}{\angstrom} = \SI{1e-10}{m}$) e il fermi o femtometro % ($\SI{1}{fm} = \SI{1e-15}{m}$). Qual è la relazione tra queste due % unità di misura? % \begin{keyans} % \item* $\SI{1}{\angstrom}=\SI{1e5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-15}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e3}{fm}$. % \end{keyans} % \end{enumext} % % \printkeyans[columns=4]{sabastiano} % % \subsubsection*{Example 2} % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-exa-2.tex} % arara: lualatex: { branch: developer } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } \documentclass{article} \usepackage[colorlinks]{hyperref} \usepackage{siunitx,amssymb,tikz,enumext} \usetikzlibrary{shapes.geometric} \sisetup{output-decimal-marker={,}} \DeclareSIUnit{\angstrom}{\textup{\AA}} \newcommand*{\mySquared}[1]{% \begin{tikzpicture}[baseline=(number.base),square/.style={regular polygon,regular polygon sides=4}] \node[square, rounded corners=1pt, inner sep=1pt, draw=none, fill=gray!40] (number) {\makebox[\height]{#1}}; \end{tikzpicture}% } \pagestyle{empty} \begin{document} \setenumext[keyans]{label=\Alph*,font=\small,nosep,wrap-label={\mySquared{##1}}} \begin{enumext}[columns=1,save-ans=sabastiano2,mark-pos=left,mark-ans=$\checkmark$,save-ref=true,show-ans=true,itemsep=0pt] \item La velocità di \qty{1,00e2}{m/s} espressa in \unit{km/h} è: \begin{keyans} \item \qty{36}{km/h}. \item* \qty{360}{km/h}. \item \qty{27,8}{km/h}. \item \qty{3,60e8}{km/h}. \end{keyans} \item In fisica nucleare si usa l'angstrom (simbolo: $\qty{1}{\angstrom} = \qty{1e-10}{m}$) e il fermi o femtometro ($\qty{1}{fm} = \qty{1e-15}{m}$). Qual è la relazione tra queste due unità di misura? \begin{keyans} \item* $\qty{1}{\angstrom}=\qty{1e5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-15}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e3}{fm}$. \end{keyans} \item La velocità di \qty{1,00e2}{m/s} espressa in \unit{km/h} è: \begin{keyans} \item \qty{36}{km/h}. \item* \qty{360}{km/h}. \item \qty{27,8}{km/h}. \item \qty{3,60e8}{km/h}. \end{keyans} \item In fisica nucleare si usa l'angstrom (simbolo: $\qty{1}{\angstrom} = \qty{1e-10}{m}$) e il fermi o femtometro ($\qty{1}{fm} = \qty{1e-15}{m}$). Qual è la relazione tra queste due unità di misura? \begin{keyans} \item* $\qty{1}{\angstrom}=\qty{1e5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-5}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e-15}{fm}$. \item $\qty{1}{\angstrom}=\qty{1e3}{fm}$. \end{keyans} \end{enumext} \printkeyans[columns=4]{sabastiano2} \end{document} \end{filecontents*} % \iffalse % % \fi % % Adapted from the response given by Florent Rougon in \href{https://tex.stackexchange.com/q/529034/7832}{Multiple choice questions with proposed answers in random order — addition of automatic correction (cross mark)} % \textattachfile[color=red,print=false]{enumext-exa-2.tex}{\faFile*[regular]}. % \setenumext[keyans]{label=\Alph*,font=\small,nosep,wrap-label={\mySquared{##1}}} % \begin{enumext}[columns=2,save-ans=sabastiano2,mark-pos=left,mark-ans=$\checkmark$,save-ref=true,show-ans=true,itemsep=0pt] % \item La velocità di \SI{1,00e2}{m/s} espressa in \si{km/h} è: % \begin{keyans} % \item \SI{36}{km/h}. % \item* \SI{360}{km/h}. % \item \SI{27,8}{km/h}. % \item \SI{3,60e8}{km/h}. % \end{keyans} % % \item In fisica nucleare si usa l'angstrom (simbolo: % $\SI{1}{\angstrom} = \SI{1e-10}{m}$) e il fermi o femtometro % ($\SI{1}{fm} = \SI{1e-15}{m}$). Qual è la relazione tra queste due % unità di misura? % \begin{keyans} % \item* $\SI{1}{\angstrom}=\SI{1e5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-15}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e3}{fm}$. % \end{keyans} % % \item La velocità di \SI{1,00e2}{m/s} espressa in \si{km/h} è: % \begin{keyans} % \item \SI{36}{km/h}. % \item* \SI{360}{km/h}. % \item \SI{27,8}{km/h}. % \item \SI{3,60e8}{km/h}. % \end{keyans} % % \item In fisica nucleare si usa l'angstrom (simbolo: % $\SI{1}{\angstrom} = \SI{1e-10}{m}$) e il fermi o femtometro % ($\SI{1}{fm} = \SI{1e-15}{m}$). Qual è la relazione tra queste due % unità di misura? % \begin{keyans} % \item* $\SI{1}{\angstrom}=\SI{1e5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-5}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e-15}{fm}$. % \item $\SI{1}{\angstrom}=\SI{1e3}{fm}$. % \end{keyans} % \end{enumext} % % \printkeyans*[columns=2]{sabastiano2} % % \subsubsection*{Example 3} % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-exa-3.tex} % arara: lualatex: { branch: developer } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } \documentclass{article} \usepackage[margin=2cm]{geometry} \usepackage{tikz} \newcommand*{\myCircled}[1]{% \begin{tikzpicture}[baseline=(number.base)] \node[circle, draw=green!10!gray, inner sep=1pt, fill=blue!30!green!10] (number) {#1}; \end{tikzpicture}% } \usepackage[colorlinks]{hyperref} \usepackage{enumext} \pagestyle{empty} \begin{document} \setenumext[keyans]{labelsep=8pt,label=\Alph*,font=\small,nosep,wrap-label={\myCircled{##1}}} \setenumext[keyans*]{labelsep=8pt,label=\Alph*,font=\small,nosep,wrap-label={\myCircled{##1}}} \setenumextmeta[enumext,2]{myroman}{no-store, label=\Roman*., noitemsep} \setenumextmeta[enumext,2]{myarabic}{no-store,list-offset=0.5cm,label=(\arabic*),noitemsep} \begin{enumext}[mode-box,save-ans=simplemc,columns=1,nosep,save-ref=true] \item First type of questions \begin{keyans*}[columns=1,noitemsep] \item value \item*[$x=5$] correct \item value \item value \end{keyans*} \item Second type of questions \begin{enumext}[myroman] \item $2\alpha+2\delta=90^{\circ}$ \item $\alpha=\delta$ \item $\angle EDF=45^{\circ}$ \end{enumext} \begin{keyans}[columns=2,noitemsep] \item I only \item II only \item I and II only \item* I and III only \item I, II, and III \end{keyans} \item Third type of questions \begin{enumext}[myarabic] \item $2\alpha+2\delta=90^{\circ}$ \item $\angle EDF=45^{\circ}$ \end{enumext} \begin{keyans}[columns=2,noitemsep] \item value \item value \item*[some note] value \item value \item value \end{keyans} \item Question with image and label below: \begin{keyanspic}[layout-sty={3,2},label-sep=3pt] \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-b}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic{\includegraphics[scale=0.15]{example-image-a}} \anspic*[A duck]{\includegraphics[scale=0.32]{example-image-duck}} \end{keyanspic} \item Question with image on left side: \begin{keyans}[mini-env=0.5\linewidth, columns=1,noitemsep] \item value \item value \item value \item*[other note] correct \item value \miniright \includegraphics[scale=0.15]{example-image-b} \end{keyans} \end{enumext} \medskip Test keys \printkeyans{simplemc} \end{document} \end{filecontents*} % \iffalse % % \fi % % A \emph{\enquote{simple multiple choice}} test \textattachfile[color=red,print=false]{enumext-exa-3.tex}{\faFile*[regular]}. % \setenumext[keyans]{label=\Alph*,font=\small,nosep,wrap-label={\myCircled{##1}}} % \begin{enumext}[save-ans=simplemc,columns=1,nosep,save-ref=true] % \item First type of questions % \begin{keyans*}[columns=2,noitemsep] % \item value % \item*[$x=5$] correct % \item value % \item value % \end{keyans*} % \item Second type of questions % \begin{enumext}[no-store,label=\Roman*.,nosep] % \item $2\alpha+2\delta=90^{\circ}$ % \item $\alpha=\delta$ % \item $\angle EDF=45^{\circ}$ % \end{enumext} % \begin{keyans}[columns=2,noitemsep] % \item I only % \item II only % \item I and II only % \item* I and III only % \item I, II, and III % \end{keyans} % \item Third type of questions % \begin{enumext}[no-store,list-offset=0.5cm,label=(\arabic*),nosep] % \item $2\alpha+2\delta=90^{\circ}$ % \item $\angle EDF=45^{\circ}$ % \end{enumext} % \begin{keyans}[columns=2,noitemsep] % \item value % \item value % \item*[some note] value % \item value % \item value % \end{keyans} % % \item Question with image and label below: % \begin{keyanspic} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-b}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic{\includegraphics[scale=0.15]{example-image-a}} % \anspic*[A duck]{\includegraphics[scale=0.32]{example-image-duck}} % \end{keyanspic} % % \item Question with image on left side: % \begin{keyans}[mini-env=0.5\linewidth, columns=1,noitemsep] % \item value % \item value % \item value % \item*[other note] correct % \item value % \miniright % \includegraphics[scale=0.15]{example-image-b} % \end{keyans} % \end{enumext} % % \smallskip % % Test keys % % \printkeyans[columns=2]{simplemc} % % \subsubsection*{Example 4} % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-exa-4.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=2cm,right=2cm]{geometry}% \usepackage[osf]{libertinus} \usepackage{unicode-math,tikzducks,graphicx,hyperref,enumext} \begin{document} \begin{enumext}[mode-box,save-ans=simplews,labelsep=10pt,columns=2,check-ans=true,show-ans=true,nosep,save-ref=true,wrap-label={\tikz[scale=0.25]\duck[signpost=\scalebox{0.6}{#1}];}] \item Factor $x^{2}-2x+1$ \anskey{$\left(x-1\right)^{2}$} \item Factor $3x+3y+3z$ \anskey{$3(x+y+z)$} \item True False \begin{enumext}[nosep] \item $\alpha > \delta$ \anskey{False} \item \LaTeX2e\ is cool? \anskey{Very True!} \end{enumext} \item Related to Linux \begin{enumext}[nosep] \item You use linux? \anskey{Yes} \item Usually uses the package manager? \anskey{Yes, \texttt{dnf}} \item Rate the following package and class \begin{enumext}[nosep] \item \texttt{xsim-exam} \anskey{doesn't exist for now :(} \item \texttt{xsim} \anskey{very good} \item \texttt{exsheets} \anskey{obsolete} \end{enumext} \end{enumext} \end{enumext} The answer to \ref{simplews:1} is \getkeyans{simplews:1} and the answer to \ref{simplews:3} is \getkeyans{simplews:3}. \printkeyans[columns=2]{simplews} \end{document} \end{filecontents*} % \iffalse % % \fi % % A \emph{\enquote{simple worksheet}} using ducks :) \textattachfile[color=red,print=false]{enumext-exa-4.tex}{\faFile*[regular]}. % % \begin{enumext}[save-ans=simplews,columns=1,check-ans=true,nosep,save-ref=true,wrap-label={\tikz[scale=0.25]\duck[signpost=\scalebox{0.6}{#1}];}] % \item Factor $x^{2}-2x+1$ \anskey{$\left(x-1\right)^{2}$} % \item Factor $3x+3y+3z$ \anskey{$3(x+y+z)$} % \item[] The following questions need to be cuaqtified :) % \item True False % \begin{enumext}[nosep] % \item $\alpha > \delta$ \anskey{False} % \item \LaTeX2e\ is cool? \anskey{Very True!} % \end{enumext} % \item Related to Linux % \begin{enumext}[nosep] % \item You use linux? \anskey{Yes} % \item Usually uses the package manager? \anskey{Yes, \texttt{dnf}} % \item Rate the following package and class % \begin{enumext}[nosep] % \item \texttt{xsim-exam} \anskey{doesn't exist for now :(} % \item \texttt{xsim} \anskey{very good} % \item \texttt{exsheets} \anskey{obsolete} % \end{enumext} % \end{enumext} % \end{enumext} % % The answer to \ref{simplews:1} is \getkeyans{simplews:1} and the answer % to \ref{simplews:3} is \getkeyans{simplews:3}. % % \printkeyans[columns=2]{simplews} % % \subsubsection*{Example 5} % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-exa-5.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } % arara: move: { files: [ enumext-exa-5-luamml-mathml.html ], target: 'enumext-exa-5-mathml.html' } \DocumentMetadata{ lang=en-US, pdfversion=2.0, pdfstandard=ua-2, testphase={phase-III,math,title,table,firstaid}, } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=2cm,right=2cm]{geometry}% \usepackage[osf]{libertinus} \usepackage{unicode-math,xcolor,graphicx,hyperref,enumext} \hypersetup { colorlinks = true, pdftitle = {Test tagged PDF for SAT style enumext package}, } \newsavebox{\satbox} \sbox\satbox{\small\textbf{67}}% \NewDocumentCommand \stylesat { m } {% \setlength{\fboxsep}{2pt}% \raisebox{7\fboxsep}{% \noindent\colorbox{black}{\textcolor{white}{\makebox[\dimeval{\labelwidth-2\fboxsep}][c]{\small\textbf{\vphantom{67}#1}}}}% \colorbox{lightgray}{\phantom{\rule[-\dp\satbox]{\dimeval{\linewidth-2\fboxsep}}{\dimeval{\dp\satbox+\ht\satbox}}}}}% } \begin{document} \setenumext[keyans]{label=\Alph*),nosep,below*={0.3cm}} \begin{enumext}[mode-box,label=\arabic*,labelwidth=20pt,labelsep=0pt,columns=2,columns-sep=30pt,save-ans=stylesat, wrap-label={\stylesat{#1}}] \item Which choice best describes what happens in the passage? \begin{keyans} \item* One character argues with another character who intrudes on her home. \item One character receives a surprising request from another character. \item One character reminisces about choices she has made over the years. \item One character criticizes another character for pursuing an unexpected course of action. \end{keyans} \item Which choice best describes what happens in the passage? \begin{keyans} \item One character argues with another character who intrudes on her home. \item One character receives a surprising request from another character. \item* One character reminisces about choices she has made over the years. \item One character criticizes another character for pursuing an unexpected course of action. \end{keyans} \item Which choice best describes what happens in the passage? \begin{keyans} \item One character argues with another character who intrudes on her home. \item* One character receives a surprising request from another character. \item One character reminisces about choices she has made over the years. \item One character criticizes another character for pursuing an unexpected course of action. \end{keyans} \item Which choice best describes what happens in the passage? \begin{keyans} \item One character argues with another character who intrudes on her home. \item One character receives a surprising request from another character. \item One character reminisces about choices she has made over the years. \item* One character criticizes another character for pursuing an unexpected course of action. \end{keyans} \end{enumext} \printkeyans[columns=4]{stylesat} \end{document} \end{filecontents*} % \iffalse % % \fi % % Adapted from the response given by Stephen in \href{https://tex.stackexchange.com/a/691544}{SAT like question format} % \textattachfile[color=red,print=false]{enumext-exa-5.tex}{\faFile*[regular]}. % \setenumext[keyans]{label=\Alph*),font=\small,nosep,wrap-label={##1}} % \begin{enumext}[label=\arabic*,labelwidth=20pt,labelsep=0pt,columns=2,save-ans=stylesat, wrap-label={\stylesat{#1}}] % \item Which choice best describes what happens in the passage? % \begin{keyans} % \item* One character argues with another character who intrudes on her home. % \item One character receives a surprising request from another character. % \item One character reminisces about choices she has made over the years. % \item One character criticizes another character for pursuing an unexpected course of action. % \end{keyans} % % \item Which choice best describes what happens in the passage? % \begin{keyans} % \item One character argues with another character who intrudes on her home. % \item One character receives a surprising request from another character. % \item* One character reminisces about choices she has made over the years. % \item One character criticizes another character for pursuing an unexpected course of action. % \end{keyans} % % \item Which choice best describes what happens in the passage? % \begin{keyans} % \item One character argues with another character who intrudes on her home. % \item* One character receives a surprising request from another character. % \item One character reminisces about choices she has made over the years. % \item One character criticizes another character for pursuing an unexpected course of action. % \end{keyans} % % \item Which choice best describes what happens in the passage? % \begin{keyans} % \item One character argues with another character who intrudes on her home. % \item One character receives a surprising request from another character. % \item One character reminisces about choices she has made over the years. % \item* One character criticizes another character for pursuing an unexpected course of action. % \end{keyans} % \end{enumext} % % \printkeyans[columns=4]{stylesat} % % \section{Tagged PDF examples} % % This section is just to show the compatibility of \mypkg*{enumext} with % \emph{tagged} \texttt{PDF} using |lualatex|. The attached files here % are just for testing and are intended as examples and, in a way, to % simplify the time of Matthew Bertucci (\texttt{@mbertucci}) when he sees this % excellent package and adds it to \href{https://github.com/latex3/tagging-project}{The LaTeX Tagged PDF repository}. % % \smallskip % % To compile the tests with |lualatex-dev| the packages \mypkg{multicol}, % \mypkg{scontents}, \mypkg{unicode-math}, \mypkg{geometry}, \mypkg{graphicx}, \mypkg{luamml} % and \mypkg{hyperref} are required along with the line: % % \smallskip % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \DocumentMetadata { lang = en-US, pdfversion = 2.0, pdfstandard = `\mydim{ua-2}`, testphase = {phase-III, math, title, table, firstaid}, } \end{examplecode} % \iffalse % % \fi % % \smallskip % % \begin{important} % All examples have been checked using \href{https://dev.verapdf-rest.duallab.com}{\texttt{veraPDF}} % together with \href{https://ngpdf.com}{\texttt{ngpdf}}. % \end{important} % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-01.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } % arara: move: { files: [ enumext-01-luamml-mathml.html ], target: 'enumext-01-mathml.html' } \DocumentMetadata { lang=en-US, pdfversion=2.0, pdfstandard=ua-2, testphase={phase-III,math,title,table,firstaid}, %uncompress, } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=1cm,right=1cm]{geometry} \usepackage{unicode-math,hyperref,enumext} \hypersetup { colorlinks = true, pdftitle = {Test tagged PDF for enumext package}, } \begin{document} \section{only enumext} Some text here \begin{enumext}[labelwidth=1cm,labelsep=0.25cm,align=left, wrap-label=\textbf{(#1}, label=\arabic*.)] \item This text is in the first level.\label{A} \begin{enumext} \item This text is in the second level.\footnote{foot note in enumext} \begin{enumext} \item This text is in the third level. \begin{enumext} \item This text is in the fourth level.\footnotemark[20] \end{enumext} \end{enumext} \end{enumext} \item[X] This text is in the first level. \item* This text is in the first level. \end{enumext} Some ref here \ref{A}\footnotetext[20]{foot note in enumext [20]} \section{only enumext*} Some text here \begin{enumext*}[columns=2,labelwidth=1cm,labelsep=0.25cm,align=left, wrap-label=\textbf{#1)}, label=(\arabic*.] \item This text is in the first level.\label{B} \item[X] This text is in the first level.\footnotemark[30] \item* This text is in the first level.\footnote{foot note in enumext*} \item This text is in the first level. \end{enumext*} Some ref here \ref{B}\footnotetext[30]{foot note in enumext* [30]} \section{enumext nested in enumext*} Some text here \begin{enumext*} \item This text is in the first level.\label{C} \item \begin{enumext}[base-fix] \item This text is in nested enumext.\label{D}\footnote{foot note in neseted enumext} \item This text is in nested enumext.\footnotemark[40] \end{enumext} \item This text is in the first level. \end{enumext*} Some refs here \ref{C} and \ref{D} \footnotetext[40]{foot note in neseted enumext [40]} \section{enumext* nested in enumext} \begin{enumext} \item This text is in the first level. \label{E} \item \begin{enumext*}[label=\roman*.] \item This text is in nested enumext*.\label{F}\footnotemark[50] \item This text is in nested enumext*.\footnote{foot note in neseted enumext*} \end{enumext*} \item This text is in the first level. \end{enumext} Some refs here \ref{E} and \ref{F} \footnotetext[50]{foot note in neseted enumext* [50]} \section{Custom ref} \begin{enumext}[ref={enumext-level-\arabic*}] \item This text is in the first level. \label{G} \item \begin{enumext*}[label=\roman*., ref={nested-\arabic{enumXi}.\roman*}] \item This text is in nested enumext*.\label{H} \item This text is in nested enumext*. \end{enumext*} \item This text is in the first level. \end{enumext} Some refs here \ref{G} and \ref{H} \end{document} \end{filecontents*} \IfFileExists{enumext-01.pdf}{}{\ShellEscape{arara enumext-01.tex}} % \iffalse % % \fi % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-02.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } % arara: move: { files: [ enumext-02-luamml-mathml.html ], target: 'enumext-02-mathml.html' } \DocumentMetadata { lang=en-US, pdfversion=2.0, pdfstandard=ua-2, testphase={phase-III,math,title,table,firstaid}, %uncompress, } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=1cm,right=1cm]{geometry} \usepackage{unicode-math,hyperref,enumext} \hypersetup { colorlinks = true, pdftitle = {Test tagged PDF for enumext package}, } \begin{document} \section{enumext + multicols} Some text here \begin{enumext}[columns=2, labelwidth=1cm,labelsep=0.25cm,align=left, wrap-label=\textbf{(#1}, label=\arabic*.),partopsep=0.5cm] \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \item[X] This text is in the first level. \item* This text is in the first level. \end{enumext} Some text here \section{enumext + minipage} Some text here \begin{enumext}[labelwidth=1cm,labelsep=0.25cm,align=left,partopsep=0.5cm,mini-env=0.4\linewidth] \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \miniright This text is in minipage. \end{enumext} \section{enumext + minipage + multicols} Some text here \begin{enumext}[columns=2,labelwidth=1cm,labelsep=0.25cm,align=left,partopsep=0.5cm,mini-env=0.4\linewidth] \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \miniright This text is in minipage. \end{enumext} Some text here \section{enumext* + minipage} Some text here \begin{enumext*}[columns=2,labelwidth=1cm,labelsep=0.25cm,align=left,partopsep=0.5cm,mini-env=0.4\linewidth, mini-right = {This text is in minipage.}] \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \item This text is in the first level. \end{enumext*} \end{document} \end{filecontents*} \IfFileExists{enumext-02.pdf}{}{\ShellEscape{arara enumext-02.tex}} % \iffalse % % \fi % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-03.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } % arara: move: { files: [ enumext-03-luamml-mathml.html ], target: 'enumext-03-mathml.html' } \DocumentMetadata { lang=en-US, pdfversion=2.0, pdfstandard=ua-2, testphase={phase-III,math,title,table,firstaid}, %uncompress, } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=1cm,right=1cm]{geometry} \usepackage{unicode-math,graphicx,hyperref,enumext} \hypersetup { colorlinks = true, pdftitle = {Test tagged PDF for enumext package}, } \begin{document} \section{enumext+keyanspic} Some text here \begin{enumext}[save-ans=test,save-sep={ },save-ref = true] \item Question with images. \begin{keyanspic}[layout-sty={3,2}] \anspic{\includegraphics[scale=0.30, alt={Un pato de color amarillo}]{example-image-duck}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula A}]{example-image-a}} \anspic*{\includegraphics[scale=0.15, alt={Una letra mayuscula B}]{example-image-b}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula C}]{example-image-c}} \anspic{\includegraphics[scale=0.15, alt={La palabra Image}]{example-image}} \end{keyanspic} \item Question with images.\label{dos} \begin{keyanspic}[label-pos=above, layout-sty={3,2}] \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula A}]{example-image-a}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula B}]{example-image-b}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula C}]{example-image-c}} \anspic{\includegraphics[scale=0.15, alt={La palabra Image}]{example-image}} \anspic*[A duck]{\includegraphics[scale=0.30, alt={Un pato de color amarillo}]{example-image-duck}} \end{keyanspic} \item Question with images. \begin{keyanspic} \anspic*[La letra A]{\includegraphics[scale=0.15, alt={Una letra mayuscula A}]{example-image-a}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula B}]{example-image-b}} \anspic{\includegraphics[scale=0.30, alt={Un pato de color amarillo}]{example-image-duck}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula C}]{example-image-c}} \anspic{\includegraphics[scale=0.15, alt={La palabra Image}]{example-image}} \end{keyanspic} \item Question with images. \begin{keyanspic}[label-pos=above] \anspic{\includegraphics[scale=0.30, alt={Un pato de color amarillo}]{example-image-duck}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula A}]{example-image-a}} \anspic*{\includegraphics[scale=0.15, alt={Una letra mayuscula B}]{example-image-b}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula C}]{example-image-c}} \anspic{\includegraphics[scale=0.15, alt={La palabra Image}]{example-image}} \end{keyanspic} \end{enumext} The answer to question \ref{dos} is \getkeyans{test:2} \printkeyans*{test} \end{document} \end{filecontents*} \IfFileExists{enumext-03.pdf}{}{\ShellEscape{arara enumext-03.tex}} % \iffalse % % \fi % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-04.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } % arara: move: { files: [ enumext-04-luamml-mathml.html ], target: 'enumext-04-mathml.html' } \listfiles \DocumentMetadata { lang=en-US, pdfversion=2.0, pdfstandard=ua-2, testphase={phase-III,math,title,table,firstaid}, %uncompress, } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=1cm,right=1cm]{geometry} \usepackage{unicode-math,graphicx,hyperref,enumext} \hypersetup { colorlinks = true, pdftitle = {Test tagged PDF for enumext package}, } \begin{document} \section{enumext + anskey + anskey*} Some text here \begin{enumext}[save-ans=test,save-sep={ },save-ref = true] \item Question A. \anskey{Answer A} \item Question B. \anskey{Answer B} \item Question C. \begin{anskey*} Answer whit \verb+code+ and more \begin{verbatim} Some code here \end{verbatim} And text \end{anskey*} \end{enumext} The answer to question \ref{test:2} is \getkeyans{test:2} \printkeyans*{test} \section{enumext* + anskey + anskey*} Some text here \begin{enumext*}[save-ans=test-2,save-sep={ },save-ref = true] \item Question A. \anskey{Answer A} \item Question B. \anskey{Answer B} \item Question C. \begin{anskey*} Answer whit \verb+code+ and more \begin{verbatim} Some code here \end{verbatim} And text \end{anskey*} \end{enumext*} \printkeyans{test-2} \end{document} \end{filecontents*} \IfFileExists{enumext-04.pdf}{}{\ShellEscape{arara enumext-04.tex}} % \iffalse % % \fi % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-05.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } % arara: move: { files: [ enumext-05-luamml-mathml.html ], target: 'enumext-05-mathml.html' } \DocumentMetadata{ lang=en-US, pdfversion=2.0, pdfstandard=ua-2, testphase={phase-III,math,title,table,firstaid}, %uncompress, } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=1cm,right=1cm]{geometry} \usepackage{unicode-math,graphicx,hyperref,enumext} \hypersetup { colorlinks = true, pdftitle = {Test tagged PDF for enumext package}, } \setenumext[print,1]{columns=2, columns-sep=1cm, font=\bfseries} \setenumext[print*]{columns=2, columns-sep=1cm,first=\bfseries} \setenumext[enumext,1]{columns=2,nosep,save-ref=true,save-sep={ },wrap-opt=\fbox{##1}, show-ans=true} \setenumext[keyans]{columns=2,noitemsep} \setenumext[keyans*]{columns=2,noitemsep} \setenumextmeta[enumext,2]{myroman}{no-store, label=\Roman*., noitemsep} \setenumextmeta[enumext,2]{myarabic}{no-store,list-offset=0.5cm,label=(\arabic*),noitemsep} \begin{document} \section{The enumext package in action} \begin{enumext}[save-ans=mytest] \item First type of questions \begin{keyans*} \item value \item*[$x=5$] correct \item value \item value \end{keyans*} \item Second type of questions \begin{enumext}[myroman] \item $2\alpha+2\delta=90^{\circ}$ \item $\alpha=\delta$ \item $\angle EDF=45^{\circ}$ \end{enumext} \begin{keyans} \item I only \item II only \item I and II only \item* I and III only \item I, II, and III \end{keyans} \item* Third type of questions \begin{enumext}[myarabic] \item $2\alpha+2\delta=90^{\circ}$ \item $\angle EDF=45^{\circ}$ \end{enumext} \begin{keyans} \item value \item value \item*[some note $y$] value \item value \item value \end{keyans} \item Question with image and label above: \begin{keyanspic}[label-pos=above, layout-sty={3,2}] \anspic*[La letra A]{\includegraphics[scale=0.15, alt={Una letra mayuscula A}]{example-image-a}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula B}]{example-image-b}} \anspic{\includegraphics[scale=0.30, alt={Un pato de color amarillo}]{example-image-duck}} \anspic{\includegraphics[scale=0.15, alt={Una letra mayuscula C}]{example-image-c}} \anspic{\includegraphics[scale=0.15, alt={La palabra Image}]{example-image}} \end{keyanspic} \item A question \begin{keyans}[mini-env=0.5\linewidth, columns=1] \item value \item value \item value \item*[other note] correct \item value \miniright \includegraphics[scale=0.15,alt={Una letra mayuscula B}]{example-image-b} \end{keyans} \item Question with image on left side: \anskey[item-star]{Mucak} \end{enumext} Some text here \section{printkeyans} Some text here \printkeyans{mytest} \section{printkeyans*} Some text here \printkeyans*{mytest} \section{foreachkeyans} Some text here \foreachkeyans[sep={\par}]{mytest} Some text here \end{document} \end{filecontents*} \IfFileExists{enumext-05.pdf}{}{\ShellEscape{arara enumext-05.tex}} % \iffalse % % \fi % % % \iffalse %<*example> % \fi \begin{filecontents*}[overwrite]{enumext-06.tex} % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer, draft: true } % arara: lualatex: { branch: developer } % arara: clean: { extensions: [ aux, log, out] } % arara: move: { files: [ enumext-06-luamml-mathml.html ], target: 'enumext-06-mathml.html' } \DocumentMetadata { lang=en-US, pdfversion=2.0, pdfstandard=ua-2, testphase={phase-III,math,title,table,firstaid}, %uncompress, } \documentclass{article} \usepackage[top=2cm,bottom=2cm,left=3cm,right=3cm]{geometry} \usepackage{unicode-math,graphicx,hyperref,enumext} \hypersetup { colorlinks = true, pdftitle = {Test tagged PDF for enumext package}, } \newlength{\descitemwd} \NewDocumentCommand \labelbx { s +m } {% \SuspendTagging{\parbox}% \IfBooleanTF{#1}% {\strut\smash{\parbox[t]{\labelwidth}{\raggedright{#2}}}}% {\strut\smash{\parbox[t]{\labelwidth}{\raggedleft{#2}}}}% \ResumeTagging{\parbox} } \begin{document} \section{Fake \texttt{itemize} environment} \noindent\begin{minipage}[t]{0.45\linewidth} \begin{enumext}[nosep, label=\textbullet] \item First level item \begin{enumext}[nosep,label=\normalfont\bfseries\textendash] \item Second level item \begin{enumext}[nosep,label=\textasteriskcentered] \item Third level item \begin{enumext}[nosep,label=\textperiodcentered] \item Fourth level item \end{enumext} \end{enumext} \end{enumext} \item First level item \end{enumext} \end{minipage}\hfill \begin{minipage}[t]{0.45\linewidth} \begin{enumext}[nosep, label=$\ast$] \item First level item \begin{enumext}[nosep,label=$\diamond$] \item Second level item \begin{enumext}[nosep,label=$\circ$] \item Third level item \begin{enumext}[nosep,label=$\star$] \item Fourth level item \end{enumext} \end{enumext} \end{enumext} \item First level item \end{enumext} \end{minipage} \section{Fake \texttt{description} environment} \settowidth{\descitemwd}{\textbf{Something long}} \begin{enumext}[label={},labelwidth=\descitemwd,font=\bfseries,noitemsep,topsep=3pt] \item[SomeThing] A short one-line description. \item[] This is an entry \emph{without} a label. \item[Something] A short \emph{one-line} description text. \item[Something long] A much \emph{longer} description text may take more than one line or more than one paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \end{enumext} \begin{enumext*}[label={},labelwidth=\descitemwd,font=\bfseries,noitemsep,topsep=3pt] \item[SomeThing] A short one-line description. \item[] This is an entry \emph{without} a label. \item[Something] A short \emph{one-line} description text. \item[Something long] A much \emph{longer} description text may take more than one line or more than one paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \end{enumext*} \begin{enumext}[label={},labelwidth=\descitemwd,list-indent=0pt,font=\bfseries,noitemsep,topsep=3pt] \item[SomeThing] A short one-line description. \item[] This is an entry \emph{without} a label. \item[Something] A short \emph{one-line} description text. \item[Something long] A much \emph{longer} description text may take more than one line or more than one paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \end{enumext} \begin{enumext*}[label={},labelwidth=\descitemwd,list-indent=0pt,font=\bfseries,noitemsep,topsep=3pt] \item[SomeThing] A short one-line description. \item[] This is an entry \emph{without} a label. \item[Something] A short \emph{one-line} description text. \item[Something long] A much \emph{longer} description text may take more than one line or more than one paragraph. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \end{enumext*} \section{Fake \texttt{description} environment in margin} \begin{enumext}[align=right, label={},labelsep=4pt,labelwidth=\descitemwd,list-offset={-\descitemwd-4pt}, font=\bfseries,noitemsep,topsep=3pt] \item[SomeThing] A short one-line description. \item This is an entry \textit{without} a label. \item[Something] A short one-line description. \item[Something long] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida mauris. \end{enumext} \begin{enumext*}[align=right, label={},labelsep=4pt,labelwidth=\descitemwd,list-offset={-\descitemwd-4pt}, font=\bfseries,noitemsep,topsep=3pt] \item[SomeThing] A short one-line description. \item This is an entry \textit{without} a label. \item[Something] A short one-line description. \item[Something long] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida mauris. \end{enumext*} \section{Fake \texttt{description} with multi-line labels} \begin{enumext}[label={},labelsep=4pt,labelwidth=\descitemwd,list-offset=-\dimeval{\descitemwd+4pt}, wrap-label*={\labelbx{#1}}, font=\bfseries,noitemsep,topsep=3pt] \item[SomeThing] A short one-line description. \item This is an entry \textit{without} a label. \item[Something] A short one-line description. \item[Something \\ long] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida mauris. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida mauris. \item[SoMeThInG \\ LoNg] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida mauris. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida mauris. \end{enumext} \end{document} \end{filecontents*} \IfFileExists{enumext-06.pdf}{}{\ShellEscape{arara enumext-06.tex}} % \iffalse % % \fi % % \begin{itemize}[topsep=1pt,partopsep=0pt,parsep=1pt,itemsep=1pt] % \item The file \myfile{enumext-01.tex} contains the basic tests for the % \myenv*{enumext} and \myenv*{enumext*} environments and the nesting % between them plus the use of the \mykey{label}, \mykey{labelwidth}, % \mykey{labelsep}, \mykey{ref}, \mykey{align} and \mykey{wrap-label} keys. % \IfFileExists{enumext-01.pdf}{Source file \textattachfile[color=red,print=false]{enumext-01.tex}{\faFile*[regular]} % and \emph{tagged} \texttt{PDF} \textattachfile[color=red,print=false]{enumext-01.pdf}{\faFilePdf[regular]}}{}.% % % \item The file \myfile{enumext-02.tex} contains the tests for the \myenv*{enumext} % and \myenv*{enumext*} environments and the support for \myenv{minipage} % and \myenv{multicols} environments using the keys \mykey{columns}, % \mykey{columns-sep}, \mykey{mini-env}, \mykey{mini-right} and % |\miniright| command. \IfFileExists{enumext-02.pdf}{Source file \textattachfile[color=red,print=false]{enumext-02.tex}{\faFile*[regular]} % and \emph{tagged} \texttt{PDF} \textattachfile[color=red,print=false]{enumext-02.pdf}{\faFilePdf[regular]}}{}.% % % \item The file \myfile{enumext-03.tex} contains the tests for the \myenv*{enumext} % and \myenv*{keyanspic} environments activated by the \mykey{save-ans} % key together with the \mykey{save-sep} and \mykey{save-ref} keys and % the |\printkeyans| command. % \IfFileExists{enumext-03.pdf}{Source file \textattachfile[color=red,print=false]{enumext-03.tex}{\faFile*[regular]} % and \emph{tagged} \texttt{PDF} \textattachfile[color=red,print=false]{enumext-03.pdf}{\faFilePdf[regular]}}{}.% % % \item The file \myfile{enumext-04.tex} contains the tests for the |\anskey| % command and the \myenv*{anskey*} environment activated by the % \mykey{save-ans} key along with the |\getkeyans| and |\printkeyans| commands. % \IfFileExists{enumext-04.pdf}{Source file \textattachfile[color=red,print=false]{enumext-04.tex}{\faFile*[regular]} % and \emph{tagged} \texttt{PDF} \textattachfile[color=red,print=false]{enumext-04.pdf}{\faFilePdf[regular]}}{}.% % % \item The file \myfile{enumext-05.tex} contains the tests for the environments % \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} activated by the key % \mykey{save-ans} together with the keys \mykey{no-store} and \mykey{show-ans} % and the commands |\setenumext|, |\setenumextmeta|, |\printkeyans| and |\foreachkeyans|. % \IfFileExists{enumext-05.pdf}{Source file \textattachfile[color=red,print=false]{enumext-05.tex}{\faFile*[regular]} % and \emph{tagged} \texttt{PDF} \textattachfile[color=red,print=false]{enumext-05.pdf}{\faFilePdf[regular]}}{}.% % % \item The file \myfile{enumext-06.tex} contains the tests for the environments % \myenv*{enumext} and \myenv*{enumext*} for \emph{fake} \myenv{itemize} and \myenv{description}. % \IfFileExists{enumext-06.pdf}{Source file \textattachfile[color=red,print=false]{enumext-06.tex}{\faFile*[regular]} % and \emph{tagged} \texttt{PDF} \textattachfile[color=red,print=false]{enumext-06.pdf}{\faFilePdf[regular]}}{}.% % \end{itemize} % % \section{The way of non-enumerated lists} % % It is possible to use (or abuse) the \myenv*{enumext} and \myenv*{enumext*} environments to % mimic \emph{non-enumerated} list environments such as \myenv{itemize} and % \myenv{description}, clearly the \mymeta{keys} to \emph{\enquote{store answers}}, % the \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} environments lose their % sense and it is not the focus of \mypkg*{enumext} package, but, why not % to do it?. % % \smallskip % % Here I leave as an example other uses of the \myenv*{enumext} % environment that can be helpful for specific purposes. The \emph{trick} % to generate these \emph{\enquote{fake environments}} is set \mykey{label}|={}| % or \mykey{label}|=|\mymarg{some} and play with the |list-indent|, |list-offset|, % |font| and |wrap-label| keys. % % \subsection*{Fake \texttt{itemize} environment} % % Here we set the \mykey{label} key using the default settings in % \hologo{LaTeX} for the four levels |\textbullet|, |\textendash|, |\textasteriskcentered| % and |\textperiodcentered| together with the % \mykey{nosep} key to reduce the vertical spaces in the left side example and set the % \mykey{label} key in \emph{mathematical mode} for the right side as % |\ast|, |\diamond|, |\circ| and |\star| for the four levels % together with the \mykey{nosep} key % % \noindent\begin{minipage}[t]{0.45\linewidth} % \begin{enumext}[nosep, label=\textbullet] % \item First level item % \begin{enumext}[nosep,label=\normalfont\bfseries\textendash] % \item Second level item % \begin{enumext}[nosep,label=\textasteriskcentered] % \item Third level item % \begin{enumext}[nosep,label=\textperiodcentered] % \item Fourth level item % \end{enumext} % \end{enumext} % \end{enumext} % \item First level item % \end{enumext} % \end{minipage}\hfill % \begin{minipage}[t]{0.45\linewidth} % \begin{enumext}[nosep, label=$\ast$] % \item First level item % \begin{enumext}[nosep,label=$\diamond$] % \item Second level item % \begin{enumext}[nosep,label=$\circ$] % \item Third level item % \begin{enumext}[nosep,label=$\star$] % \item Fourth level item % \end{enumext} % \end{enumext} % \end{enumext} % \item First level item % \end{enumext} % \end{minipage} % % \subsection*{Fake \texttt{description} environment} % % Here we set \mykey{label}|={}| and |list-indent=2.5em,font=\bfseries|. % % \begin{enumext}[label={},list-indent=2.5em,font=\bfseries,noitemsep,topsep=3pt] % \item[SomeThing] A short one-line description. % \item[] This is an entry \emph{without} a label. % \item[Something] A short \emph{one-line} description text. % \item[Something long] A much \emph{longer} description text may take % more than one line or more than one paragraph. % % Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod % tempor incididunt ut labore et dolore magna aliqua. % \end{enumext} % % If we add |list-indent=0pt| you get \emph{widest style}: % % \begin{enumext}[label={},list-indent=0pt,font=\bfseries,noitemsep,topsep=3pt] % \item[SomeThing] A short one-line description. % \item[] This is an entry \emph{without} a label. % \item[Something] A short \emph{one-line} description text. % \item[Something long] A much \emph{longer} description text may take % more than one line or more than one paragraph. % % Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod % tempor incididunt ut labore et dolore magna aliqua. % \end{enumext} % % \begin{important}* % The small space at the beginning of the \emph{\enquote{unlabeled entry}} corresponds to % |\labelsep| and can be removed using |\hspace{-\labelsep}| at the % beginning of the line. % \end{important} % % \smallskip % % \begin{important} % When \emph{tagged} PDF is active the default \myenv{description} style % is NOT available due to the redefinition of |\makelabel| for the % \mykey{align} key which uses |\makebox| in this case, meaning that % |\item|\myoarg{content} will not extend beyond |\labelwidth| which % causes overlaps, % \end{important} % % \subsection*{Description indented by label} % % Here we set \mykey{label}|={}| and we will give a convenient value to % \mykey{labelsep} and \mykey{labelwidth}, for example we can take as reference our % \emph{longest label} and pass it as value using: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=none] \newlength{\descitemwd} \settowidth{\descitemwd}{\textbf{Something long}} \end{examplecode} % \iffalse % % \fi % % and then use \mykey{labelsep}|=4pt,|\mykey{labelwidth}|=\descitemwd,font=\bfseries|. % % \newlength{\descitemwd} % \settowidth{\descitemwd}{\textbf{Something long}} % \begin{enumext}[label={},labelsep=4pt,labelwidth=\descitemwd,font=\bfseries,noitemsep,topsep=3pt] % \item[SomeThing] A short one-line description. % \item[] This is an entry \textit{without} a label. % \item[Something] A short one-line description. % \item[Something long] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. % Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. % Curabitur dictum gravida mauris. % \end{enumext} % % The environment can be translated so that the \mymeta{labels} are on % the left margin calculating the value passed to the \mykey{list-offset} % key, in this case it will be equal to the sum of the values set by the % \mykey{labelwidth} and \mykey{labelsep} keys finally resulting as % \mykey{list-offset}|={-\descitemwd - 4pt}|. % % \begin{enumext}[label={},labelsep=4pt,labelwidth=\descitemwd,list-offset={-\descitemwd-4pt}, font=\bfseries,noitemsep,topsep=3pt] % \item[SomeThing] A short one-line description. % \item This is an entry \textit{without} a label. % \item[Something] A short one-line description. % \item[Something long] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. % Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. % Curabitur dictum gravida mauris. % \end{enumext} % % If we add \mykey{align}|=right| it will look like this: % % \begin{enumext}[label={},align=right,labelsep=4pt,labelwidth=\descitemwd,list-offset={-\descitemwd - 4pt}, font=\bfseries,noitemsep,topsep=3pt] % \item[SomeThing] A short one-line description. % \item This is an entry \textit{without} a label. % \item[Something] A short one-line description. % \item[Something long] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. % Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. % Curabitur dictum gravida mauris. % \end{enumext} % % \begin{important}* % At this point we have used \mykey{list-offset}|={-\descitemwd - 4pt}| instead of % |list-offset={-\labelwidth - \labelsep}|, % this is because the parameters |\labelwidth| and |\labelsep| take the % default values, as if we had not set \mykey{label}. % \end{important} % % \subsection*{Description with multi-line labels} % % The \mykey{label} key does not accept \emph{multiline material}, this % is where the \mykey{wrap-label} and \mykey{wrap-label*} keys comes into % play. Unlike the \mypkg{enumitem} package, the \mykey{align} key only % supports three options, so what we will do is create a command in the % style |\parleft| of \mypkg{enumitem} that allows us to place \emph{multiline labels} % using |\parbox|. % % \iffalse %<*example> % \fi \begin{examplecode}[frame=none] \NewDocumentCommand \labelbx { s +m } {% \SuspendTagging{\parbox}% \IfBooleanTF{#1} {\strut\smash{\parbox[t]{\labelwidth}{\raggedright{#2}}}}% {\strut\smash{\parbox[t]{\labelwidth}{\raggedleft{#2}}}}% \ResumeTagging{\parbox}% } \end{examplecode} % \iffalse % % \fi % % Now we just need to set |wrap-label*={\labelbx{#1}}|.%^^A |mode-box| and % % \begin{enumext}[mode-box,label={},labelsep=4pt,labelwidth=\descitemwd,list-offset=-\dimeval{\descitemwd+4pt}, wrap-label*={\labelbx{#1}}, font=\bfseries,noitemsep,topsep=3pt] % \item[SomeThing] A short one-line description. % \item This is an entry \textit{without} a label. % \item[Something] A short one-line description. % \item[Something \\ long] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. % Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. % Curabitur dictum gravida mauris. % % Lorem ipsum dolor sit amet, consectetuer adipiscing elit. % Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. % Curabitur dictum gravida mauris. % % \item[SoMeThInG \\ LoNg] A much longer description. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. % Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. % Curabitur dictum gravida mauris. % \end{enumext} % % \section*{Final notes} % % The original implementation (if you can call it that) of the ideas that % led to the creation of \mypkg*{enumext} were some macros using the \mypkg{enumerate}\cite{enumerate} % package for personal use created in early 2003, the code was quite % questionable, but functional for these simple requirements. % % \medskip % % With the great answers given by Christian Hupfer in % \href{https://tex.stackexchange.com/a/364763/7832}{Create a fake label ref % using list} and the answer given by David Carlisle in % \href{https://tex.stackexchange.com/a/363963/7832}{Change the use of label % ref by data save in an array (list)} I managed to create a more solid % code than the original version, now using the \mypkg{l3prop}\cite{inter3} and \mypkg{l3seq}\cite{inter3} % modules together with the \mypkg{hyperref}\cite{hyperref} and \mypkg{enumitem}\cite{enumitem} packages, which did % the job, but with some limitations. % % \smallskip % % As time went by I took these limitations as a personal challenge which % I called \emph{\enquote{reinventing the wheel}}, since there were packages and classes % that did more or less what I was looking for, but did not fit my simple % requirements. This \emph{\enquote{reinventing the wheel}} finally ended up becoming % \mypkg*{enumext}. % % \subsubsection*{Why list environments?} % % The answer is simple, first I love the beauty of its syntax and many of % what I had already written used the \myenv{enumerate} environment or % lists created using the \mypkg{enumitem} package. In my mind I thought: % how complicated could it be to write a package that looked like % \mypkg{enumitem}? It seemed simple enough, of course I didn't have in % mind the mess I was getting into working with \myenv{list} % environments, \myenv{minipage} and adding support for the % \mypkg{multicol} and \mypkg{hyperref} packages. % % Of course, seeing the final result of the experiment % \emph{\enquote{reinventing the wheel}} I am quite satisfied. % % \subsubsection*{Why not random questions and other utilities} % % The \emph{\enquote{random}} type questions I love and hate them at the % same time, although they simplify a lot the work when creating a % multiple choice test, but you lose the beauty of typessetting a % document with \hologo{LaTeX}, that is to say the output does not always % look as nice as it should, even if they are only alternatives these % must follow a certain order when presented either numerical or % presentation, that said handling that using \emph{nested lists} is quite % complicated so I do not classify to be implemented. % % \subsubsection*{Why has it taken so long?} % % One of the setbacks, beyond my laziness, was including compatibility % with \emph{tagged} \texttt{PDF}. To be honest, it's something I never % considered at any point, but I firmly believe that being able to create % \emph{accessible documents} provides a great opportunity in the world of % mathematics education. From my perspective as a \emph{high school} teacher, % beyond theorems and deep mathematics, the use of exercise lists is one % of the most common things. Being able to open the way to work in % parallel with those who have different abilities is really important % and I regret not having looked into this in the past. I hope that % \mypkg*{enumext} serves this purpose and inspires more users and % authors to follow this path. % % \let\stdsection\section % \def\section*#1{\stdsection{#1}} % % \begin{thebibliography}{10} % % \bibitem{exam} \textsc{Hirschhorn, Philip}. \enquote{Using the % \textsf{exam} document class}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/exam}, 2023. % % \bibitem{xsim} \textsc{Niederberger, Clemens}. \enquote{\textsf{xsim} – eXercise % Sheets IMproved}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/xsim}, 2023. % % \bibitem{multicol} \textsc{Mittelbach, Frank}. \enquote{An % environment for \textsf{multicolumn} output}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/multicol}, 2024. % % \bibitem{scontents} \textsc{González, Pablo}. \enquote{\textsf{scontents} - Stores % \hologo{LaTeX} contents in memory or files}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/scontents}, 2024. % % \bibitem{enumerate} The \hologo{LaTeX} Project. \enquote{\textsf{enumerate} – Enumerate % with redefinable labels}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/enumerate}, 2024. % % \bibitem{enumitem} \textsc{Bezos, Javier}. \enquote{Customizing lists % with the \textsf{enumitem} package}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/enumitem}, 2019 % % \bibitem{latexref} \textsc{Berry, Karl}. \enquote{\hologo{LaTeX2e}: An % Unofficial Reference Manual}. Available from \textsc{ctan}, % \url{https://ctan.org/pkg/latex2e-help-texinfo}, 2024. % % \bibitem{hyperref} The \hologo{LaTeX} Project. \enquote{Extensive support % for hypertext in \hologo{LaTeX}}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/hyperref}, 2024. % % \bibitem{footnotehyper} \textsc{Burnol, Jean-François}. \enquote{The \textsf{footnotehyper} % package}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/footnotehyper}, 2021. % % \bibitem{expl3} The \hologo{LaTeX} Project. \enquote{The \textsf{expl3} % package}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/l3kernel}, 2024. % % \bibitem{inter3} The \hologo{LaTeX} Project. \enquote{The \hologo{LaTeX}3 % Interfaces}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/l3kernel}, 2024. % % \bibitem{latex2e} The \hologo{LaTeX} Project. \enquote{The \hologo{LaTeX2e} % sources}. Available from % \textsc{ctan}, \url{https://ctan.org/tex-archive/macros/latex/base}, 2024. % % \bibitem{userguide} The \hologo{LaTeX} Project. \enquote{\hologo{LaTeX} for authors % current version}. Available from % \textsc{ctan}, \url{https://ctan.org/pkg/latex-base}, 2024. % % \bibitem{luavisual} \textsc{Gundlach, Patrick}. \enquote{The \textsf{lua-visual-debug} % package}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/lua-visual-debug}, 2023. % % \bibitem{shortlst} \textsc{Lemvig, Mogens}. \enquote{The \textsf{shortlst} % package}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/shortlst}, 1998. % % \bibitem{tasks} \textsc{Niederberger, Clemens}. \enquote{\textsf{tasks} – Horizontally % columned lists}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/tasks}, 2022. % % \bibitem{tagpdf} \textsc{Fischer, Ulrike}. \enquote{\textsf{tagpdf} – \hologo{LaTeX} % kernel code for PDF tagging}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/tagpdf}, 2024. % % \bibitem{latexlab} The \hologo{LaTeX} Project. \enquote{\textsf{latex-lab} – \hologo{LaTeX} % laboratory}. Available from % \textsc{ctan}, \url{https://www.ctan.org/pkg/latex-lab}, 2024. % % \bibitem{ltsockets} \textsc{Mittelbach, Frank}. \enquote{\hologo{LaTeX}’s % socket management}. Available from % \textsc{ctan}, \url{https://ctan.org/tex-archive/macros/latex/base}, 2024. % % \end{thebibliography} % % \let\section\stdsection % % \section{Change history} % \label{sec:changes} % % \setlist[itemize,1]{label=\textendash,wide=0.5em,nosep,noitemsep,leftmargin=10pt} % \newlength\descrwidth % \settowidth{\descrwidth}{\textsf{v1.0a, --- 2023-08-18} } % % \begin{description}[font=\small\sffamily,wide=0pt,style=multiline,leftmargin=1.1\descrwidth,nosep,noitemsep] % \item [\fileversion{} \, \filedate] % \begin{itemize} % \item First public release. % \end{itemize} % \end{description} % % \newpage % % \indexprologue{ % The italic numbers denote the pages where the corresponding entry is % described.} % % \printindex[userdoc] % % \newpage % % \StartImplementation % % \StopEventually{^^A % \newgeometry{top=0.5in,bottom=0.3in,left=1.0in,right=0.5in,footskip=0.2in,headheight=1cm,headsep=0.27cm} % \addtocontents{toc}{\protect\setcounter{tocdepth}{2}} % \cleardoublepage % \phantomsection % \indexprologue{ % The italic numbers denote the pages where the corresponding entry is % described, the numbers underlined and all others indicate the line on % which they are implemented in the package code. % } % \printindex % } % % \newgeometry{top=0.5in,bottom=0.3in,left=1.95in,right=0.5in,footskip=0.2in,headheight=1cm,headsep=0.27cm} % % \section{Implementation} % \label{sec:Implementation} % \addtocontents{toc}{\protect\setcounter{tocdepth}{0}} % % The most recent publicly released version of \mypkg*{enumext} is % available at \textsc{ctan}: \url{https://www.ctan.org/pkg/enumext}. % While general feedback via email is welcomed, specific bugs or % feature requests should be reported through the issue % tracker: \textcolor{gray}{\scriptsize\faIcon[regular]{github}} \url{https://github.com/pablgonz/enumext/issues}. % % \smallskip % % \begin{important}* % The documentation presented here is far from professional, it contains % a lot of obvious information that to the eye of a \hologo{TeX}pert are % superfluous, but, after so many years developing this project is the % only way to remember what does what. % \end{important} % % \subsection{General conventions} % % Variables containing \lstinline+i+, \lstinline+ii+, \lstinline+iii+ and % \lstinline+iv+ are associated by level with the \myenv*{enumext} % environment, variables containing \lstinline+v+ are associated with the % \myenv*{keyans} environment, variables containing \lstinline+vi+ are % associated with the \myenv*{keyanspic} environment, variables % containing \lstinline+vii+ are associated with the \myenv*{enumext*} % environment and variables containing \lstinline+viii+ are associated % with the \myenv*{keyans*} environment. % % \medskip % % To simplify writing and documentation some variables and functions that % are common to the different levels of the environments are described % using a capital \enquote{\texttt{\textcolor{optcolor}{X}}}. % % \medskip % % The temporary function \myvarenv{__@@_tmp:n} is used in % different parts of the package code for variable creation or execution % of other functions that are grouped into this one. % % \medskip % % All variables and functions defined in this package are private and % are NOT intended to work or be used by another package or module. % % \subsection{Initial set up} % % Start the \pkg{DocStrip} guards. % \begin{macrocode} %<*package> % \end{macrocode} % Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention) for % \pkg{l3doc} class. % \begin{macrocode} %<@@=enumext> % \end{macrocode} % % \subsection{Declaration of the package} % % First we will make sure we have a minimum (super updated) version of % \hologo{LaTeX} to work correctly. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}[2024-11-01] % \end{macrocode} % Now declare the \mypkg*{enumext} package. % \begin{macrocode} \ProvidesExplPackage {enumext} {2024-11-01} {1.0} {Enumerate exercise sheets} % \end{macrocode} % Finally check if the \mypkg{multicol} and \mypkg{scontents} packages % are loaded, if not we load it. % \begin{macrocode} \hook_gput_code:nnn {begindocument} {enumext} { \IfPackageLoadedTF { multicol } { \msg_info:nnn { enumext } { package-load } { multicol } } { \msg_info:nnn { enumext } { package-not-load } { multicol } \RequirePackage{multicol}[2024-05-23] } \IfPackageLoadedTF { scontents } { \msg_info:nnn { enumext } { package-load } { scontents } } { \msg_info:nnn { enumext } { package-not-load } { scontents } \RequirePackage{scontents} } } % \end{macrocode} % % \subsection{Definition of variables} % % Variables that do not appear in this section are created by means of % \cs[no-index]{keys_define:nn} or some function described below. % % \begin{variable}[int]{\l_@@_level_int, \l_@@_level_h_int, \l_@@_anskey_level_int, % \l_@@_keyans_level_int, \l_@@_keyans_level_h_int, % \l_@@_keyans_pic_level_int,} % Integer variables will control the nesting levels of the environments % and |\anskey| command. % \iffalse %% Variable for levels and nesting off all environments and \anskey. % \fi % \begin{macrocode} \int_new:N \l_@@_level_int \int_new:N \l_@@_level_h_int \int_new:N \l_@@_anskey_level_int \int_new:N \l_@@_keyans_level_int \int_new:N \l_@@_keyans_level_h_int \int_new:N \l_@@_keyans_pic_level_int % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_starred_bool, \g_@@_starred_bool, \l_@@_starred_first_bool, % \l_@@_standar_bool, \g_@@_standar_bool, \l_@@_standar_first_bool, % \l_@@_anskey_env_bool, \l_@@_keyans_env_bool,\g_@@_start_line_tl, % \g_@@_envir_name_tl, \l_@@_envir_name_tl} % Internal variables used by functions \cs{@@_is_not_nested:}, % \cs{@@_is_on_first_level:} and \cs{@@_keyans_name_and_start:} (\S\ref{fun:utilities}). % \iffalse %% Internal vars for levels and nesting off all environments. % \fi % \begin{macrocode} \bool_new:N \l_@@_starred_bool \bool_new:N \g_@@_starred_bool \bool_new:N \l_@@_starred_first_bool \bool_new:N \l_@@_standar_bool \bool_new:N \g_@@_standar_bool \bool_new:N \l_@@_standar_first_bool \bool_new:N \l_@@_anskey_env_bool \bool_new:N \l_@@_keyans_env_bool \tl_new:N \g_@@_start_line_tl \tl_new:N \g_@@_envir_name_tl \tl_new:N \l_@@_envir_name_tl % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_counter_i_tl, \l_@@_counter_ii_tl, % \l_@@_counter_iii_tl, \l_@@_counter_iv_tl, % \l_@@_counter_v_tl,\l_@@_counter_vi_tl, % \l_@@_counter_vii_tl,\l_@@_counter_viii_tl} % % Variables to store the \emph{\enquote{name of the counters}} % \icounter{enumXi}, \icounter{enumXii}, \icounter{enumXiii} and % \icounter{enumXiv} for \myenv*{enumext} environment, % \icounter{enumXv} for \myenv*{keyans} environment and % \icounter{enumXvi} for the \myenv*{keyanspic} environment. % The counters \icounter{enumXvii} and \icounter{enumXviii} are used % by \myenv*{enumext*} and \myenv*{keyans*} environments. % % \smallskip % % The initial values of these variables are set by the function % \cs{@@_define_counters:Nn} (\S\ref{int:counters}) and then modified by the function % \cs{@@_label_style:Nnn} used by \mykey{label} key (\S\ref{key:label-ref}). % \iffalse %% Variable for counters % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \tl_new:c { l_@@_counter_#1_tl } } \clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\c_@@_counter_style_tl, \l_@@_ref_key_arg_tl, % \l_@@_ref_the_count_tl, \l_@@_the_counter_X_tl, % \l_@@_renew_the_count_X_tl, } % Internal variables used by \mykey{ref} key (\S\ref{key:label-ref}). % \iffalse %% Variables used by |ref| key. % \fi % \begin{macrocode} \tl_const:Nn \c_@@_counter_style_tl { { arabic } { roman } { Roman } { alph } { Alph } } \tl_new:N \l_@@_ref_key_arg_tl \tl_new:N \l_@@_ref_the_count_tl \cs_set_protected:Npn \@@_tmp:n #1 { \tl_new:c { l_@@_renew_the_count_#1_tl } \tl_new:c { l_@@_the_counter_#1_tl } \tl_set:ce { l_@@_the_counter_#1_tl } { \exp_not:c { theenumX#1 } } } \clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}{\g_@@_resume_int, \g_@@_resume_vii_int, \l_@@_resume_name_tl, % \l_@@_resume_active_bool, \g_@@_starred_series_tl, % \g_@@_standar_series_tl,} % % Internal variables used by \mykey{resume}, \mykey{resume*} and % \mykey{series} keys (\S\ref{key:series}). % \iffalse %% Variables used by |series|, |resume| and |resume*| keys implementation. % \fi % \begin{macrocode} \int_new:N \g_@@_resume_int \int_new:N \g_@@_resume_vii_int \tl_new:N \l_@@_resume_name_tl \bool_new:N \l_@@_resume_active_bool \tl_new:N \g_@@_standar_series_tl \tl_new:N \g_@@_starred_series_tl % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_current_widest_dim, \g_@@_counter_styles_tl, % \g_@@_widest_label_tl, \l_@@_label_width_by_box} % The variable \cs{l_@@_current_widest_dim} stores the current % label width, the variable \cs{g_@@_counter_styles_tl} stores % the default \mymeta{label style} and the variable % \cs{g_@@_widest_label_tl} the label width. These variables are % used by \mykey{widest} (\S\ref{key:start-widest}) and \mykey{label} (\S\ref{key:label}) keys. % \iffalse %% Variables used by |label|, |ref| and |widest| keys. % \fi % \begin{macrocode} \dim_new:N \l_@@_current_widest_dim \tl_new:N \g_@@_counter_styles_tl \tl_new:N \g_@@_widest_label_tl \box_new:N \l_@@_label_width_by_box % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_leftmargin_tmp_X_bool, \l_@@_leftmargin_tmp_X_dim, % \l_@@_leftmargin_X_dim, \l_@@_itemindent_X_dim,} % The boolean variable \myvarenv{l__@@_leftmargin_tmp_X_bool} and the % dimensional variable \myvarenv{l__@@_leftmargin_tmp_X_dim} % are used by the \mykey{list-indent} key (\S\ref{key:list-indent}). % The variables \myvarenv{l__@@_leftmargin_X_dim} and % \myvarenv{l__@@_itemindent_X_dim} are used and set by the function % \myvarenv{__@@_calc_hspace:NNNNNNNNNNNN} (\S\ref{int:leftmargin}). % \iffalse %% Add \l__enumext_leftmargin_tmp_X_bool, \l__enumext_leftmargin_tmp_X_dim, %% \l__enumext_leftmargin_X_dim, \l__enumext_itemindent_X_dim used by the %% function \enumext_calc_hspace:NNNNNNNNNNNN and |list-indent| key. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \bool_new:c { l_@@_leftmargin_tmp_#1_bool } \dim_new:c { l_@@_leftmargin_tmp_#1_dim } \dim_new:c { l_@@_leftmargin_#1_dim } \dim_new:c { l_@@_itemindent_#1_dim } } \clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}[int]{ \l_@@_multicols_above_X_skip, \l_@@_multicols_below_X_skip, % \g_@@_multicols_right_X_skip, \l_@@_align_label_pos_X_str,} % Internal variables used by \mykey{columns} key (\S\ref{vspace:multi}) % and \mykey{align} key (\S\ref{key:label}). % \iffalse %% Variables used by |columns| and |align| keys in |enumext| and |keyans| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \skip_new:c { l_@@_multicols_above_#1_skip } \skip_new:c { l_@@_multicols_below_#1_skip } \skip_new:c { g_@@_multicols_right_#1_skip } \str_new:c { l_@@_align_label_pos_#1_str } } \clist_map_inline:nn { i, ii, iii, iv, v } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\g_@@_minipage_stat_int, \l_@@_minipage_temp_skip, % \l_@@_minipage_left_skip, \l_@@_minipage_right_skip, % \l_@@_minipage_after_skip, \g_@@_minipage_right_skip, % \g_@@_minipage_after_skip, \l_@@_minipage_left_X_dim, % \l_@@_minipage_active_X_bool,} % Internal variables used by \ics*{miniright} command (\S\ref{cmd:miniright}) % and the keys \mykey{mini-right}, \mykey{mini-right*}, \mykey{mini-env} % and \mykey{mini-sep} (\S\ref{key:mini-multi}, \S\ref{vspace:minipage}). % \iffalse %% Variables used by |miniright|, |mini-env|, |mini-sep| and |\miniright|. % \fi % \begin{macrocode} \int_new:N \g_@@_minipage_stat_int \skip_new:N \l_@@_minipage_temp_skip \skip_new:N \l_@@_minipage_left_skip \skip_new:N \l_@@_minipage_right_skip \skip_new:N \l_@@_minipage_after_skip \skip_new:N \g_@@_minipage_right_skip \skip_new:N \g_@@_minipage_after_skip \cs_set_protected:Npn \@@_tmp:n #1 { \dim_new:c { l_@@_minipage_left_#1_dim } \bool_new:c { l_@@_minipage_active_#1_bool } } \clist_map_inline:nn { i, ii, iii, iv, v, vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_wrap_label_X_bool, \l_@@_wrap_label_opt_X_bool, % \l_@@_start_X_int, \l_@@_fake_item_indent_X_tl, \l_@@_label_fill_left_X_tl, % \l_@@_label_fill_right_X_tl, \l_@@_vspace_a_star_X_bool, % \l_@@_vspace_b_star_X_bool,} % The bool vars \myvarenv{l__@@_wrap_label_X_bool} and % \myvarenv{l__@@_wrap_label_opt_X_bool} are used by \mykey{wrap-label} % and \mykey{wrap-label*} keys (\S\ref{key:label}), the integer % \myvarenv{l__@@_start_X_int} are used by the \mykey{start} and \mykey{start*} keys (\S\ref{key:start-widest}), % the token list \myvarenv{l__@@_fake_item_indent_X_tl } is used by \mykey{itemindent} key (\S\ref{key:fake-indent}), % the variables \myvarenv{l__@@_label_fill_left_X_tl} and \myvarenv{l__@@_label_fill_left_X_tl} are used by the % \mykey{align} key (\S\ref{key:label}). The boolean vars \myvarenv{l__@@_vspace_a_star_X_bool}, % \myvarenv{l__@@_vspace_b_star_X_bool} are used by \mykey{above}, % \mykey{above*}, \mykey{below} and \mykey{below*} keys (\S\ref{key:before}). % \iffalse %% Internal variables used by |wrap-label|, |start*|, |start|, |align|, |above| and |below| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \bool_new:c { l_@@_wrap_label_#1_bool } \bool_new:c { l_@@_wrap_label_opt_#1_bool } \int_new:c { l_@@_start_#1_int } \tl_new:c { l_@@_fake_item_indent_#1_tl } \tl_new:c { l_@@_label_fill_left_#1_tl } \tl_new:c { l_@@_label_fill_right_#1_tl } \bool_new:c { l_@@_vspace_a_star_#1_bool } \bool_new:c { l_@@_vspace_b_star_#1_bool } } \clist_map_inline:nn { i, ii, iii, iv, v, vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_store_active_bool, \l_@@_store_name_tl, % \g_@@_store_name_tl, \l_@@_store_anskey_arg_tl, % \l_@@_store_anskey_env_tl, \l_@@_store_anskey_opt_tl, % \l_@@_store_current_label_tl, \l_@@_store_current_opt_arg_tl, % \l_@@_store_current_label_tmp_tl,} % % The variable \cs{l_@@_store_active_bool} setting by % \mykey{save-ans} key (\S\ref{key:save-ans}) activates all the % mechanism related to \ics*{anskey}, \myenv*{anskey*}, \myenv*{keyans}, % \myenv*{keyans*} and \myenv*{keyanspic} environments. % % \smallskip % % The variable \cs{l_@@_store_name_tl} saves the \mymarg{store name} % set by the \mykey{save-ans} key of the \emph{sequence} and \emph{prop % list} in which we will store, the variable \cs{g_@@_store_name_tl} % it's just a global copy of \mymarg{store name} used by different functions. % % \smallskip % % The variable \cs{l_@@_store_anskey_arg_tl} save the % \emph{argument} of \ics*{anskey} (\S\ref{cmd:anskey}) and the variables % \cs{l_@@_store_anskey_env_tl} and \cs{l_@@_store_anskey_opt_tl} save the % \mymeta{body} and the \mymeta{keys} of the environment \myenv*{anskey*} (\S\ref{env:anskey}). % % \smallskip % % The variables \cs{l_@@_store_current_label_tl} and % \cs{l_@@_store_current_opt_arg_tl} save the \emph{current label} and % \emph{optional argument} of \ics*{item*} (\S\ref{cmd:item-starred}) and \ics*{anspic*} % (\S\ref{cmd:anspic}) for the \myenv*{keyans}, \myenv*{keyans*} and % \myenv*{keyanspic} environments. % % \smallskip % % The variable \cs{l_@@_store_current_label_tmp_tl} is a temporary variable used % by \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} at various points. % \iffalse %% Variables used by |save-ans| key. % \fi % \begin{macrocode} \bool_new:N \l_@@_store_active_bool \tl_new:N \l_@@_store_name_tl \tl_new:N \g_@@_store_name_tl \tl_new:N \l_@@_store_anskey_arg_tl \tl_new:N \l_@@_store_anskey_env_tl \tl_new:N \l_@@_store_anskey_opt_tl \tl_new:N \l_@@_store_current_label_tl \tl_new:N \l_@@_store_current_opt_arg_tl \tl_new:N \l_@@_store_current_label_tmp_tl % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_setkey_tmpa_tl, \l_@@_setkey_tmpb_tl, % \l_@@_setkey_tmpa_int, \l_@@_setkey_tmpa_seq, % \l_@@_setkey_tmpb_seq,} % Internal variables used by the command \ics*{setenumext} (\S\ref{cmd:setenumext}). % \iffalse %% Variables used by |\setenumext|. % \fi % \begin{macrocode} \tl_new:N \l_@@_setkey_tmpa_tl \tl_new:N \l_@@_setkey_tmpb_tl \int_new:N \l_@@_setkey_tmpa_int \seq_new:N \l_@@_setkey_tmpa_seq \seq_new:N \l_@@_setkey_tmpb_seq % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_meta_path_tl, \l_@@_foreach_print_seq, % \l_@@_foreach_name_prop_tl, \g_@@_foreach_default_keys_tl,} % Internal variables used by the |\printkeyans| command (\S\ref{cmd:printkeyans}) % and |\foreachkeyans| command (\S\ref{cmd:foreachkeyans}). % \begin{macrocode} \tl_new:N \l_@@_meta_path_tl \seq_new:N \l_@@_foreach_print_seq \tl_new:N \l_@@_foreach_name_prop_tl \tl_new:N \g_@@_foreach_default_keys_tl % \end{macrocode} % \end{variable} % % % \begin{variable}[int]{\l_@@_print_keyans_starred_tl, \l_@@_print_keyans_star_bool, % \l_@@_mark_position_str, \g_@@_item_symbol_aux_tl, % \l_@@_print_keyans_X_tl, \l_@@_store_save_key_X_tl, % \l_@@_store_save_key_X_bool, \l_@@_store_upper_level_X_bool,} % Internal variables used by command \ics*{printkeyans} % (\S\ref{cmd:printkeyans}), \mykey{show-pos} key (\S\ref{int:storage-system}), % \mykey{item-sym*} key (\S\ref{key:item-starred}), \mykey{save-key} key % (\S\ref{key:save-key}) and \emph{\enquote{storing structure}}. % \iffalse %% Variables used by |\printkeyans|, |mark-pos|, |item-sym*|, |save-key| and storing structure in |enumext| and |enumext*|. % \fi % \begin{macrocode} \tl_new:N \l_@@_print_keyans_starred_tl \bool_new:N \l_@@_print_keyans_star_bool \str_new:N \l_@@_mark_position_str \tl_new:N \g_@@_item_symbol_aux_tl \cs_set_protected:Npn \@@_tmp:n #1 { \tl_new:c { l_@@_print_keyans_#1_tl } \tl_new:c { l_@@_store_save_key_#1_tl } \bool_new:c { l_@@_store_save_key_#1_bool } \bool_new:c { l_@@_store_upper_level_#1_bool } } \clist_map_inline:nn { i, ii, iii, iv, vii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_anspic_args_seq, \l_@@_anspic_mini_width_dim, % \l_@@_anspic_above_int,\l_@@_anspic_below_int, % \l_@@_anspic_label_above_bool, \l_@@_anspic_mini_pos_str, % \g_@@_keyans_pic_parsep_skip, \l_@@_anspic_label_box, \l_@@_anspic_body_box, % \l_@@_anspic_label_htdp_dim, \l_@@_anspic_body_htdp_dim,} % Internal variables used by \myenv*{keyanspic} environment and % \ics*{anspic} command (\S\ref{env:keyanspic}). % \iffalse %% Variables used by |\anspic| and |keyanspic|. % \fi % \begin{macrocode} \seq_new:N \l_@@_anspic_args_seq \dim_new:N \l_@@_anspic_mini_width_dim \int_new:N \l_@@_anspic_above_int \int_new:N \l_@@_anspic_below_int \bool_new:N \l_@@_anspic_label_above_bool \str_new:N \l_@@_anspic_mini_pos_str \skip_new:N \g_@@_keyans_pic_parsep_skip \box_new:N \l_@@_anspic_label_box \box_new:N \l_@@_anspic_body_box \dim_new:N \l_@@_anspic_label_htdp_dim \dim_new:N \l_@@_anspic_body_htdp_dim % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_check_answers_bool,\g_@@_check_ans_key_bool, % \l_@@_check_start_line_env_tl, \g_@@_check_starred_cmd_int, % \g_@@_item_anskey_int, \g_@@_item_number_int, % \g_@@_item_number_bool, \g_@@_item_answer_diff_int,} % Internal variables used by \emph{\enquote{internal check answer}} mechanism % (\S\ref{int:check-answer}) used by the \mykey{check-ans} and % \mykey{no-store} keys and check for starred commands \ics*{item*} % in \myenv*{keyans} and \myenv*{keyans*} environments and \ics*{anspic*} % in \myenv*{keyanspic} environment. % \iffalse %% Variables used by check-answer mechanism, |check-ans| and |no-store| keys. % \fi % \begin{macrocode} \bool_new:N \l_@@_check_answers_bool \bool_new:N \g_@@_check_ans_key_bool \tl_new:N \l_@@_check_start_line_env_tl \int_new:N \g_@@_check_starred_cmd_int \int_new:N \g_@@_item_anskey_int \int_new:N \g_@@_item_number_int \bool_new:N \l_@@_item_number_bool \int_new:N \g_@@_item_answer_diff_int % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_hyperref_bool, \l_@@_footnotes_key_bool,} % The boolean variable \cs{l_@@_hyperref_bool} will determine if the % \mypkg{hyperref} package is present or load in memory % (\S\ref{pkg:hyperref}). The boolean variable \cs{l_@@_footnotes_key_bool} % determine if \mypkg{hyperref} is load with key |hyperfootnotes=true|. % % \iffalse %% Variables used for hyperref detection. % \fi % \begin{macrocode} \bool_new:N \l_@@_hyperref_bool \bool_new:N \l_@@_footnotes_key_bool % \end{macrocode} % \end{variable} % % \begin{variable}[int]{ \l_@@_newlabel_arg_one_tl, \l_@@_newlabel_arg_two_tl, % \l_@@_write_aux_file_tl, \l_@@_label_copy_X_tl, } % % Internal variables used by \mykey{save-ref} key (\S\ref{int:storage-system}). % The variables \myvarenv{l__@@_label_copy_X_tl} correspond to temporary % copies of the \mymeta{labels} defined by level on which operations will be performed. % % \smallskip % % The variables \cs{l_@@_newlabel_arg_one_tl} and \cs{l_@@_newlabel_arg_two_tl} % will be used to form the arguments passed to the function % \cs{@@_newlabel:nn} (\S\ref{fun:newlabel}) and the variable \cs{l_@@_write_aux_file_tl} % will be in charge of executing the writing code in the |.aux| file. % \iffalse %% Variables used by |save-ref| key (internal label and ref). % \fi % \begin{macrocode} \tl_new:N \l_@@_newlabel_arg_one_tl \tl_new:N \l_@@_newlabel_arg_two_tl \tl_new:N \l_@@_write_aux_file_tl \cs_set_protected:Npn \@@_tmp:n #1 { \tl_new:c { l_@@_label_copy_#1_tl } } \clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}{ \g_@@_footnote_standar_int, \g_@@_footnote_starred_int, % \g_@@_footnote_standar_arg_seq, \g_@@_footnote_starred_arg_seq, % \g_@@_footnote_standar_int_seq, \g_@@_footnote_starred_int_seq} % Internal variables used for redefinition of |\footnote| (\S\ref{ltx:footnote}). % \iffalse %% Variables used by |footnote| redefinition. % \fi % \begin{macrocode} \int_new:N \g_@@_footnote_standar_int \int_new:N \g_@@_footnote_starred_int \seq_new:N \g_@@_footnote_standar_arg_seq \seq_new:N \g_@@_footnote_starred_arg_seq \seq_new:N \g_@@_footnote_standar_int_seq \seq_new:N \g_@@_footnote_starred_int_seq % \end{macrocode} % \end{variable} % % \begin{variable}[int]{\l_@@_item_starred_X_bool, l_@@_item_column_pos_X_int, % \g_@@_item_count_all_X_int, \l_@@_joined_item_X_int, % \l_@@_joined_item_aux_X_int, \l_@@_tmpa_X_int, \l_@@_tmpa_X_dim, % \l_@@_item_text_X_box, \l_@@_joined_width_X_dim, % \l_@@_item_width_X_dim, \g_@@_item_symbol_aux_X_tl, % \l_@@_align_label_X_str, \g_@@_minipage_active_X_bool, % \l_@@_miniright_code_X_box , \g_@@_minipage_center_X_bool, % \g_@@_minipage_right_X_dim, \g_@@_minipage_right_X_skip,} % Internal variables used by \myenv*{enumext*} and \myenv*{keyans*} environments. % \iffalse %% Variables used by |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \bool_new:c { l_@@_item_starred_#1_bool } \int_new:c { l_@@_item_column_pos_#1_int } \int_new:c { g_@@_item_count_all_#1_int } \int_new:c { l_@@_joined_item_#1_int } \int_new:c { l_@@_joined_item_aux_#1_int } \int_new:c { l_@@_tmpa_#1_int } \dim_new:c { l_@@_tmpa_#1_dim } \box_new:c { l_@@_item_text_#1_box } \dim_new:c { l_@@_joined_width_#1_dim } \dim_new:c { l_@@_item_width_#1_dim } \tl_new:c { g_@@_item_symbol_aux_#1_tl } \str_new:c { l_@@_align_label_#1_str } \bool_new:c { g_@@_minipage_active_#1_bool } \box_new:c { l_@@_miniright_code_#1_box } \bool_new:c { g_@@_minipage_center_#1_bool } \dim_new:c { g_@@_minipage_right_#1_dim } \skip_new:c { g_@@_minipage_right_#1_skip } } \clist_map_inline:nn { vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{variable} % % \begin{variable}{\c_@@_all_envs_clist,} % An internal |clist-var| variable to run with \myvarenv{__@@_tmp:n}. % \begin{macrocode} \clist_const:Nn \c_@@_all_envs_clist { {level-1}{i}, {level-2}{ii}, {level-3}{iii}, {level-4}{iv}, {keyans}{v}, {enumext*}{vii}, {keyans*}{viii} } % \end{macrocode} % \end{variable} % % \subsection{Some utility functions} % % \begin{macro}[int]{\keys_precompile:neN, \seq_use:NV,} % Non-standard kernel variants used by the |\printkeyans| command % (\S\ref{cmd:printkeyans}) and |\foreachkeyans| command (\S\ref{cmd:foreachkeyans}). % \begin{macrocode} \cs_generate_variant:Nn \keys_precompile:nnN { neN } \cs_generate_variant:Nn \seq_use:Nn { NV } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_at_begin_document:n} % A internal \emph{\enquote{hook}} function used for copying plain % \myenv{list} and \myenv{minipage} environments definition and % \mypkg{hyperref} detection. % \iffalse %% A internal "hooks" functions used for copying and execute code. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_at_begin_document:n #1 { \hook_gput_code:nnn {begindocument} {enumext} { #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_after_env:nn, \@@_before_env:nn} % A internal \emph{\enquote{hook}} functions for execute code \mykey{mini-right} % and \mykey{mini-right*} keys outside the \myenv*{enumext*} and % \myenv*{keyans*} environments and print \mykey{check-ans} outside the % \myenv*{enumext} and \myenv*{enumext*} environments. % \begin{macrocode} \cs_new_protected:Npn \@@_after_env:nn #1 #2 { \hook_gput_code:nnn {env/#1/after} {enumext} {#2} } \cs_new_protected:Npn \@@_before_env:nn #1 #2 { \hook_gput_code:nnn {env/#1/before} {enumext} {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_level:} % Function for check current level in \myenv*{enumext}. % \iffalse %% Function to check current level. % \fi % \begin{macrocode} \cs_new:Nn \@@_level: { \int_to_roman:n { \l_@@_level_int } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_if_is_int:nT, \@@_if_is_int:nF, \@@_if_is_int:nTF} % A conditional function to know if the variable we are passing is % an integer used by \mykey{start} and \mykey{widest} keys. % This function is taken directly from the answer given by Henri Menke % in \href{https://tex.stackexchange.com/a/427559}{How to test if an expl3 function argument is an integer expression?}. % \iffalse %% Function to check integer variables used by |start| and |widest| keys. % \fi % \begin{macrocode} \prg_new_protected_conditional:Npnn \@@_if_is_int:n #1 { T, F, TF } { \regex_match:nnTF { ^[\+\-]?[\d]+$ } {#1} % $ { \prg_return_true: } { \prg_return_false: } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_regex_counter_style:} % The internal function \cs{@@_regex_counter_style:} replace the ‘|*|’ % with the actual counter of the running level and is used by % the \mykey{ref} key. % It loops through the defined counter styles in \cs{c_@@_counter_style_tl} % and replace ‘|*|’ by real command, for example, looking for \ilabel{arabic*} % and replacing that by \ics{arabic}\mymarg{counter} defined % on the current level. % \iffalse %% Regex for replace '*' for |ref| key. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_regex_counter_style: { \tl_map_inline:Nn \c_@@_counter_style_tl { \regex_replace_once:nnN { \c{##1}\* } { \c{##1}\cB{\u{l_@@_ref_the_count_tl}\cE} } \l_@@_ref_key_arg_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_show_length:nnn} % Internal function used by \mykey{show-length} key to show % \emph{\enquote{all lengths}} calculated and use in % \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and % \myenv*{keyans*} environments. % \iffalse %% Function to show list lengths used by |show-length| key. % \fi % \begin{macrocode} \cs_new:Npn \@@_show_length:nnn #1 #2 #3 { * ~ #2 \prg_replicate:nn { 14 - \str_count:n {#2} } { ~ } = ~ \use:c { #1_use:c } { l_@@_#2_#3_#1 } \\ } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_unskip_unkern:} % The function \cs{@@_unskip_unkern:} will remove the last \mymeta{skip} % or \mymeta{kern} at execution time using the values ​​\mydim{11} and % \mydim{12} of |\lastnodetype| to apply |\unskip| or |\unkern| according % to the case. % \iffalse %% Remove last skip or kern. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_unskip_unkern: { \int_case:nnT { \lastnodetype } { { 11 }{ \unskip } { 12 }{ \unkern } } } % \end{macrocode} % \end{macro} % % \subsubsection{Utilities for environments and levels}\label{fun:utilities} % % \begin{macro}{\@@_is_not_nested:, \@@_is_on_first_level:} % The function \cs{@@_is_not_nested:} set the variables \cs{g_@@_standar_bool} % and \cs{g_@@_starred_bool} to \emph{\enquote{true}} only if the % environments \myenv*{enumext} and \myenv*{enumext*} are NOT nested % in each other and save the environment name in \cs{l_@@_envir_name_tl}. % \iffalse %% Function to check/set current environment for |enumext| and |enumext*|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_is_not_nested: { \str_case:en { \@currenvir } { {enumext} { \tl_set:Nn \l_@@_envir_name_tl { enumext } \bool_lazy_and:nnT { \bool_not_p:n { \g_@@_standar_bool } } { \int_compare_p:nNn { \l_@@_level_h_int } = { 0 } } { \bool_gset_true:N \g_@@_standar_bool } } {enumext*} { \tl_set:Nn \l_@@_envir_name_tl { enumext* } \bool_lazy_and:nnT { \bool_not_p:n { \g_@@_starred_bool } } { \int_compare_p:nNn { \l_@@_level_int } = { 0 } } { \bool_gset_true:N \g_@@_starred_bool } } } } % \end{macrocode} % The function \cs{@@_is_on_first_level:} will set the variables % \cs{l_@@_standar_first_bool} (\S\ref{key:save-ans}), % \cs{l_@@_starred_first_bool} (\S\ref{key:save-ans}) and % \cs{l_@@_anskey_env_bool} (\S\ref{env:anskey}) to \emph{\enquote{true}} % only if the environment is not nested and we are in the \emph{\enquote{first level}} % of it . We will also save the \emph{start line number} of each environment % in the variable \cs{g_@@_start_line_tl} and the \emph{name} of each % environment in the variable \cs{g_@@_envir_name_tl} to use in messages % related to the \mykey{check-ans} key and |.log| file. % \iffalse %% Function to check/set first level vars for |enumext| and |enumext*|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_is_on_first_level: { \bool_lazy_all:nT { { \bool_if_p:N \g_@@_standar_bool } { \int_compare_p:nNn { \l_@@_level_int } = { 1 } } { \int_compare_p:nNn { \l_@@_level_h_int } = { 0 } } } { \bool_set_true:N \l_@@_standar_first_bool \bool_set_true:N \l_@@_anskey_env_bool \tl_gset:Nn \g_@@_envir_name_tl { enumext } \tl_gset:Ne \g_@@_start_line_tl { on ~ line ~ \exp_not:V \inputlineno } } \bool_lazy_all:nT { { \bool_if_p:N \g_@@_starred_bool } { \int_compare_p:nNn { \l_@@_level_h_int } = { 1 } } { \int_compare_p:nNn { \l_@@_level_int } = { 0 } } } { \bool_set_true:N \l_@@_starred_first_bool \bool_set_true:N \l_@@_anskey_env_bool \tl_gset:Nn \g_@@_envir_name_tl { enumext* } \tl_gset:Ne \g_@@_start_line_tl { on ~ line ~ \exp_not:V \inputlineno } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_keyans_name_and_start:} % The function \cs{@@_keyans_name_and_start:} will save the start line % number and name of the environments \myenv*{keyans}, \myenv*{keyans*} and % \myenv*{keyanspic} in the variables \cs{l_@@_check_start_line_env_tl} % and \cs{l_@@_envir_name_tl} to use in the \cs{@@_check_starred_cmd:n} function. % \iffalse %% Function to save the current name and start line for |keyans|, |keyans*| and |keyanspic|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_name_and_start: { \str_case:en { \@currenvir } { {keyans} { \tl_set:Nn \l_@@_envir_name_tl { keyans } \tl_set:Ne \l_@@_check_start_line_env_tl { in ~ 'keyans' ~ start ~ on ~ line ~ \exp_not:V \inputlineno } } {keyans*} { \tl_set:Nn \l_@@_envir_name_tl { keyans* } \tl_set:Ne \l_@@_check_start_line_env_tl { in ~ 'keyans*' ~ start ~ on ~ line ~ \exp_not:V \inputlineno } } {keyanspic} { \tl_set:Nn \l_@@_envir_name_tl { keyanspic } \tl_set:Ne \l_@@_check_start_line_env_tl { in ~ 'keyanspic' ~ start ~ on ~ line ~ \exp_not:V \inputlineno } } } } % \end{macrocode} % \end{macro} % % \subsubsection{Utilities for log and terminal} % % \begin{macro}{\@@_reset_global_vars:, \@@_reset_global_int:, % \@@_reset_global_bool:, \@@_reset_global_tl:,} % The function \cs{@@_reset_global_vars:} will be passed to the function % \cs{@@_execute_after_env:} and will return the global variables to % their default values after being used. % \iffalse %% Reset all global vars after use in hook function. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_reset_global_vars: { \@@_reset_global_int: \@@_reset_global_bool: \@@_reset_global_tl: } \cs_new_protected:Nn \@@_reset_global_int: { \int_gzero:N \g_@@_item_number_int \int_gzero:N \g_@@_item_anskey_int \int_gzero:N \g_@@_item_answer_diff_int } \cs_new_protected:Nn \@@_reset_global_bool: { \bool_gset_false:N \g_@@_check_ans_key_bool \bool_gset_false:N \g_@@_standar_bool \bool_gset_false:N \g_@@_starred_bool } \cs_new_protected:Nn \@@_reset_global_tl: { \tl_gclear:N \g_@@_store_name_tl \tl_gclear:N \g_@@_start_line_tl \tl_gclear:N \g_@@_envir_name_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_log_global_vars:, \@@_log_answer_vars:} % The function \cs{@@_log_global_vars:} will be passed to the function % \cs{@@_execute_after_env:} and write to the |.log| file the number of % elements saved in the \emph{prop list} and \emph{sequence} created by the % \mykey{save-ans} key along with the value of the integer variable % created for the \mykey{resume} key. % \iffalse %% Write all global vars after use in hook function. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_log_global_vars: { \msg_log:nneeee { enumext } { prop-seq-int-hook } { \g_@@_store_name_tl } { \prop_count:c { g_@@_ \g_@@_store_name_tl _prop } } { \seq_count:c { g_@@_ \g_@@_store_name_tl _seq } } { \int_use:c { g_@@_resume_ \g_@@_store_name_tl _int } } } % \end{macrocode} % The function \cs{@@_log_answer_vars:} will be passed to the function % \cs{@@_execute_after_env:} and write to the |.log| file the number % of items and answers along with the difference between them. % \iffalse %% Write all global vars for check-answer after use in hook function. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_log_answer_vars: { \msg_log:nneee { enumext } { item-answer-hook } { \int_use:N \g_@@_item_number_int } { \int_use:N \g_@@_item_anskey_int } { \int_eval:n { \g_@@_item_number_int - \g_@@_item_anskey_int} } } % \end{macrocode} % \end{macro} % % \subsection{Copying \env{list} and \env{minipage} environments} % % The \myenv{list} environment provided by \hologo{LaTeX} has the % following plain form: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=none] \list`\mymarg{arg one}\mymarg{arg two}` \item`\myoarg{opt}` \endlist \end{examplecode} % \iffalse % % \fi % % And \myenv{minipage} environment provided by \hologo{LaTeX} has the % following (simplified) plain form: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=none] \minipage`\myoarg{pos}\myoarg{height}\myoarg{inner-pos}\mymarg{width}` `\mymeta{internal implement}` \endminipage \end{examplecode} % \iffalse % % \fi % % As a precaution we copy them using \cs{@@_at_begin_document:n} in % case any package redefines the \myenv{list} environment or a related % command. % % \smallskip % % \begin{important} % For compatibility with \emph{tagged} \texttt{PDF} we should use % |\NewCommandCopy| and not |\cs_new_eq:NN| for |\item|. When % \emph{tagged} \texttt{PDF} is active |\item| is redefined using % \mypkg{ltcmd} (see \mypkg{latex-lab-block}\cite{latexlab}). % \end{important} % % \smallskip % % \begin{macro}{\@@_start_list:nn, \@@_stop_list:, \@@_item_std:w, % \@@_minipage:w, \@@_endminipage:,} % The functions \cs{@@_start_list:nn} and \cs{@@_stop_list:} correspond % to copies of |\list| and |\endlist| from plain definition of \myenv{list} % environment, the function \cs{@@_item_std:w} is a copy of the |\item| command. % \iffalse %% Copy |list| environment and |\item| command. % \fi % \begin{macrocode} \@@_at_begin_document:n { \cs_new_eq:NN \@@_start_list:nn \list \cs_new_eq:NN \@@_stop_list: \endlist \NewCommandCopy \@@_item_std:w \item } % \end{macrocode} % The functions \cs{@@_minipage:w} and \cs{@@_endminipage:} correspond % to copies of |\minipage| and |\endminipage| from plain definition of % \myenv{minipage} environment. % \iffalse %% Copy |minipage| environment. % \fi % \begin{macrocode} \@@_at_begin_document:n { \cs_new_eq:NN \@@_minipage:w \minipage \cs_new_eq:NN \@@_endminipage: \endminipage } % \end{macrocode} % \end{macro} % % \subsection{Compatibility with hyperref and footnotehyper}\label{pkg:hyperref} % % \begin{macro}{\@@_after_hyperref:, \@@_hypertarget:nn, \@@_phantomsection:} % First we define the necessary rules using \emph{\enquote{hooks}} to % determine if the \mypkg{hyperref} package is loaded. % \iffalse %% Detection off |hyperref| package with |hyperfootnotes=true|. % \fi % \begin{macrocode} \hook_gput_code:nnn { begindocument } { enumext } { \@@_after_hyperref: } \hook_gset_rule:nnnn { begindocument } { enumext } { after } { hyperref } % \end{macrocode} % The function \cs{@@_after_hyperref:} sets the state of the boolean % variable \cs{l_@@_hyperref_bool} to \enquote{true} if the package is % loaded. At this point we will use the public macro |\IfHyperBoolean| % to determine if the |hyperfootnotes=true| key is present, if so, we % set the state of the boolean variable \cs{@@_footnotes_key_bool} to % \enquote{true}. % \begin{macrocode} \cs_new_protected:Nn \@@_after_hyperref: { \IfPackageLoadedTF { hyperref } { \msg_info:nnn { enumext } { package-load } { hyperref } \bool_set_true:N \l_@@_hyperref_bool \IfHyperBoolean{hyperfootnotes} { \bool_set_true:N \l_@@_footnotes_key_bool } { } } { } % \end{macrocode} % If the state of the variable \cs{l_@@_footnotes_key_bool} is true we % will check if the package \mypkg{footnotehyper} is loaded, in case it % is not present, we will set the value of \cs{l_@@_footnotes_key_bool} % to false and we will redefine |\footnote|. % \iffalse %% Detection off |footnotehyper| package. % \fi % \begin{macrocode} \bool_if:NT \l_@@_footnotes_key_bool { \IfPackageLoadedTF { footnotehyper } { \msg_info:nnn { enumext } { package-load } { footnotehyper } } { \bool_set_false:N \l_@@_footnotes_key_bool } } % \end{macrocode} % The functions \cs{@@_hypertarget:nn} and \cs{@@_phantomsection:} % correspond to the internal copies of \ics{hypertarget} and % \ics{phantomsection}. If the boolean variable \cs{l_@@_hyperref_bool} % is false the functions \cs{@@_hypertarget:nn} and \cs{@@_phantomsection:} % will be disabled. % \begin{macrocode} \bool_if:NTF \l_@@_hyperref_bool { \cs_new_eq:NN \@@_hypertarget:nn \hypertarget \cs_new_eq:NN \@@_phantomsection: \phantomsection } { \cs_new_eq:NN \@@_hypertarget:nn \use_none:nn \cs_new_eq:NN \@@_phantomsection: \prg_do_nothing: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_newlabel:nn,}\label{fun:newlabel} % The function \cs{@@_newlabel:nn} write the information to the |.aux| % file when using the \mykey{save-ref} key. The arguments taken by the % function are: % % \begin{arguments} % \item \cs{l_@@_newlabel_arg_one_tl} % \item \cs{l_@@_newlabel_arg_two_tl} % \end{arguments} % % \smallskip % % \begin{important}* % The trick here is to manage the number of arguments passed to % \ics{newlabel}|{#1}{#2}| according to the presence of the \mypkg{hyperref} % package. % \end{important} % % \smallskip % % \iffalse %% Write internal |label| in |.aux| file for |save-ref| key. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_newlabel:nn #1 #2 { \protected@write \@auxout { } { \token_to_str:N \newlabel {#1} { {#2} \bool_if:NT \l_@@_hyperref_bool { { \thepage } {#2} {#1} } { } } } \@@_hypertarget:nn {#1} { } \@@_phantomsection: } % \end{macrocode} % \end{macro} % % \subsection{Internal redefining \cs{footnote} command}\label{ltx:footnote} % % To keep the correct numbering of \ics{footnote} and to make it work % correctly in the \myenv*{enumext*} and \myenv*{keyans*} environments % and \mykey{mini-env} key it is necessary to redefine the |\footnote| command. % This implementation is adapted from the answer given by Clea F. Rees (\texttt{@cfr}) % in \href{https://tex.stackexchange.com/a/700092}{footnotes in boxes compatible with hyperref}. % % \begin{macro}[int]{\@@_footnotetext:nn, \@@_renew_footnote:, % \@@_print_footnote:, \@@_renew_footnote_mini:, % \@@_print_footnote_mini:,} % Redefinition of the |\footnote| command using |\footnotetext| and % |\footnotemark| for the \mykey{mini-env} key in the \myenv*{enumext} and % \myenv*{keyans} environments. % \iffalse %% Redefining |\footnote| for key |mini-env| in |enumext| and |keyans| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_footnotetext:nn { \footnotetext[#1]{#2} } \cs_new_protected:Nn \@@_renew_footnote: { \RenewDocumentCommand \footnote { o +m } { \tl_if_novalue:nTF {##1} { \stepcounter{footnote} \int_gset_eq:Nc \g_@@_footnote_standar_int { c@footnote } } { \int_gset:Nn \g_@@_footnote_standar_int { ##1 } } \footnotemark [ \g_@@_footnote_standar_int ] \seq_gput_right:Nn \g_@@_footnote_standar_arg_seq { ##2 } \seq_gput_right:NV \g_@@_footnote_standar_int_seq \g_@@_footnote_standar_int } } \cs_new_protected:Nn \@@_print_footnote: { \seq_if_empty:NF \g_@@_footnote_standar_int_seq { \seq_map_pairwise_function:NNN \g_@@_footnote_standar_int_seq \g_@@_footnote_standar_arg_seq \@@_footnotetext:nn } \seq_gclear:N \g_@@_footnote_standar_arg_seq \seq_gclear:N \g_@@_footnote_standar_int_seq } % \end{macrocode} % The \myenv*{enumext*} and \myenv*{keyans*} environments are implemented % using \myenv{minipage} so we must also redefine |\footnote| to keep % these numbering as if it were part of the document. % \iffalse %% Redefining |\footnote| for |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_renew_footnote_mini: { \RenewDocumentCommand \footnote { o +m } { \tl_if_novalue:nTF {##1} { \stepcounter{footnote} \int_gset_eq:Nc \g_@@_footnote_starred_int { c@footnote } } { \int_gset:Nn \g_@@_footnote_starred_int { ##1 } } \footnotemark [ \g_@@_footnote_starred_int ] \seq_gput_right:Nn \g_@@_footnote_starred_arg_seq { ##2 } \seq_gput_right:NV \g_@@_footnote_starred_int_seq \g_@@_footnote_starred_int } } \cs_new_protected:Nn \@@_print_footnote_mini: { \seq_if_empty:NF \g_@@_footnote_starred_int_seq { \seq_map_pairwise_function:NNN \g_@@_footnote_starred_int_seq \g_@@_footnote_starred_arg_seq \@@_footnotetext:nn } \seq_gclear:N \g_@@_footnote_starred_arg_seq \seq_gclear:N \g_@@_footnote_starred_int_seq } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_renew_footnote_standar:,\@@_print_footnote_standar:, % \@@_renew_footnote_starred:,\@@_print_footnote_starred:,} % We encapsulate the redefinition of |\footnote| to pass it to internal % \myvarenv*{__@@_mini_page} environment used by the \mykey{mini-env} % key in the \myenv*{enumext} and \myenv*{keyans} environments. We will % run the redefinition when \emph{tagged} \texttt{PDF} is active or when % the \mypkg{footnotehyper} package is not loaded. % \begin{macrocode} \cs_new_protected:Nn \@@_renew_footnote_standar: { \bool_if:NT \g_@@_standar_bool { \IfDocumentMetadataTF { \@@_renew_footnote: } { \bool_if:NF \l_@@_footnotes_key_bool { \@@_renew_footnote: } } } } \cs_new_protected:Nn \@@_print_footnote_standar: { \bool_if:NT \g_@@_standar_bool { \IfDocumentMetadataTF { \@@_print_footnote: } { \bool_if:NF \l_@@_footnotes_key_bool { \@@_print_footnote: } } } } % \end{macrocode} % We encapsulate the redefinition of |\footnote| to pass it to the % \myenv*{enumext*} and \myenv*{keyans*} environments. We will run the % redefinition when \emph{tagged} \texttt{PDF} is active or when the % \mypkg{footnotehyper} package is not loaded. % \begin{macrocode} \cs_new_protected:Nn \@@_renew_footnote_starred: { \IfDocumentMetadataTF { \@@_renew_footnote_mini: } { \bool_if:NF \l_@@_footnotes_key_bool { \@@_renew_footnote_mini: } } } \cs_new_protected:Nn \@@_print_footnote_starred: { \IfDocumentMetadataTF { \@@_print_footnote_mini: } { \bool_if:NF \l_@@_footnotes_key_bool { \@@_print_footnote_mini: } } } % \end{macrocode} % In \myenv*{enumext*} and \myenv*{keyans*} environments we need to use % \emph{\enquote{hooks}} to print |\footnote| with support for % \emph{tagged} \texttt{PDF}. % \begin{macrocode} \@@_after_env:nn { enumext* } { \@@_print_footnote_starred: } \@@_after_env:nn { keyans* } { \@@_print_footnote_starred: } % \end{macrocode} % \end{macro} % % \subsection{The internal \env{minipage} environment} % % \begin{macro}[int]{\@@_internal_mini_page:, @@_mini_env*} % The function \cs{@@_internal_mini_page:} creates a internal % \myvarenv*{__@@_mini_page} environment (\emph{custom version} of % \myenv{minipage}) setting the |\if@minipage| switch to \emph{\enquote{false}} % to allow spaces at the \emph{\enquote{above}} of the environment, % plus we will add |\skip_vertical:N \c_zero_skip| to maintain alignment % on \emph{\enquote{top}} in the first part and |\skip_vertical:N \c_zero_skip| % in the second part to allow spaces \emph{\enquote{below}}. This environment % will be used internally by the \mykey{mini-env} key, it is NOT documented % in the user interface and is for internal use only. Within this environment % we redefine |\footnote| to make them look the same as if they were % elsewhere in the document. This function is passed to the function % \cs{@@_safe_exec:} in the \myenv*{enumext} environment definition (\S\ref{env:enumext}) % and \cs{@@_safe_exec_vii:} in the \myenv*{enumext*} environment % definition (\S\ref{env:starred}) % \iffalse %% Function for define a internal |minipage| environment with |\footnote| support. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_internal_mini_page: { \int_compare:nNnT { \l_@@_level_int } = { 0 } { \DeclareDocumentEnvironment{@@_mini_page}{ m } { \@@_renew_footnote_standar: \@@_minipage:w [ t ] { ##1 } \legacy_if_gset_false:n { @minipage } \skip_vertical:N \c_zero_skip } { \skip_vertical:N \c_zero_skip \@@_endminipage: \@@_print_footnote_standar: } } } % \end{macrocode} % \end{macro} % % \subsection{Definition of public dimension}\label{dim:public} % % The package \mypkg*{enumext} only provides a single public dimension % |\itemwidth| and is intended for user convenience only and is not % for internal use as such. This dimension is set in all environments % and is only used by the \mykey{wrap-ans} key at its default value. % \iffalse %% Public dimension |\itemwidth| % \fi % \begin{macrocode} \dim_zero_new:N \itemwidth % \end{macrocode} % % \subsection{Definition of counters}\label{int:counters} % % \begin{macro}[int]{\@@_define_counters:Nn,enumXi, enumXii, enumXiii, % enumXiv, enumXv, enumXvi, enumXvii, enumXviii} % To create the necessary \emph{\enquote{counters}} we must first % make sure that they are not already defined by the user or a % package such as \mypkg{enumitem}, otherwise a error will be % returned and the package loading will be aborted. The arguments % taken by the function are: % % \begin{arguments} % \item A token list \myvarenv{l__@@_counter_X_tl} for \emph{\enquote{store}} the counter's name. % \item The counter's name. % \end{arguments} % % \iffalse %% Definition of counters. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_define_counters:Nn #1 #2 { \cs_if_exist:cTF { c@ #2 } { \msg_fatal:nnn { enumext } { counters }{ #2 } } { \tl_set:Nn #1 { #2 } \newcounter { #2 } } } % \end{macrocode} % The counters created here are \icounter{enumXi}, \icounter{enumXii}, % \icounter{enumXiii} and \icounter{enumXiv} for \myenv*{enumext} % environment, \icounter{enumXv} for \myenv*{keyans} environment, % \icounter{enumXvi} for \myenv*{keyanspic} environment, \icounter{enumXvii} for % \myenv*{enumext*} and \icounter{enumXviii} for the \myenv*{keyans*} % environments. % \begin{macrocode} \@@_define_counters:Nn \l_@@_counter_i_tl { enumXi } \@@_define_counters:Nn \l_@@_counter_ii_tl { enumXii } \@@_define_counters:Nn \l_@@_counter_iii_tl { enumXiii } \@@_define_counters:Nn \l_@@_counter_iv_tl { enumXiv } \@@_define_counters:Nn \l_@@_counter_v_tl { enumXv } \@@_define_counters:Nn \l_@@_counter_vi_tl { enumXvi } \@@_define_counters:Nn \l_@@_counter_vii_tl { enumXvii } \@@_define_counters:Nn \l_@@_counter_viii_tl { enumXviii } % \end{macrocode} % \end{macro} % % \subsection{Definition of labels} % % This part of the code is inspired by the \mypkg{enumitem} package. The % idea is to be able to access the counters using \ilabel{arabic*}, % \ilabel{Alph*}, \ilabel{alph*}, \ilabel{Roman*} and \ilabel{roman*} % to use them in the \mykey{label} key. % % \begin{macro}{\@@_register_counter_style:Nn} % These \mymeta{counters} will be used as default \mymeta{labels} if % the \mykey{label} key is not used for the different levels of the % \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and \myenv*{keyans*} % environments, so it is necessary to get a default value for \mykey{labelwidth} % from these \mymeta{labels} at the same time. % \iffalse %% Register of counters style. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_register_counter_style:Nn #1 #2 { \tl_const:cn { c_@@_widest_ \cs_to_str:N #1 _tl } {#2} \tl_gput_right:Nn \g_@@_counter_styles_tl {#1} } \@@_register_counter_style:Nn \arabic { 0 } \@@_register_counter_style:Nn \Alph { M } \@@_register_counter_style:Nn \alph { m } \@@_register_counter_style:Nn \Roman { VIII } \@@_register_counter_style:Nn \roman { viii } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_label_width_by_box:Nn, \@@_label_width_by_box:cv} % The function \cs{@@_label_width_by_box:Nn} set the default \ics{labelwidth} % using a box width if no \mykey{labelwidth} key is passed. % \iffalse %% Set default label width using a box width. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_label_width_by_box:Nn #1 #2 { \hbox_set:Nn \l_@@_label_width_by_box {#2} \dim_set:Nn #1 { \box_wd:N \l_@@_label_width_by_box } } \cs_generate_variant:Nn \@@_label_width_by_box:Nn { cv } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_label_style:Nnn, \@@_label_style:cvn} % The function \cs{@@_label_style:Nnn} is used by the \mykey{label} % key to creates the variables containing the \mymeta{label style} % and will allow to use \ilabel{arabic*}, \ilabel{Alph*}, \ilabel{alph*}, % \ilabel{Roman*} and \ilabel{roman*} as arguments. % % It loops through the defined counter styles in \cs{g_@@_counter_styles_tl} % (\ics{arabic}, \ics{alph}, \ics{Alph}, \ics{roman}, and \ics{Roman}) for example, % looking for \ilabel{roman*} and replacing that by \ics{roman}\mymarg{counter}, % and doing the same for the \cs{g_@@_widest_label_tl} to keep both in sync. % \iffalse %% Function to support |*| in |label| key. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_label_style:Nnn #1 #2 #3 { \tl_clear_new:N #1 \tl_put_right:Ne #1 { \tl_trim_spaces:n {#3} } \tl_gset_eq:NN \g_@@_widest_label_tl #1 \tl_map_inline:Nn \g_@@_counter_styles_tl { \tl_replace_all:Nne #1 { ##1* } { \exp_not:N ##1 {#2} } \tl_greplace_all:Nne \g_@@_widest_label_tl { ##1* } { \tl_use:c { c_@@_widest_ \cs_to_str:N ##1 _tl } } } \@@_label_width_by_box:Nn \l_@@_current_widest_dim { \tl_use:N \g_@@_widest_label_tl } \tl_set_eq:cN { the #2 } #1 } \cs_generate_variant:Nn \@@_label_style:Nnn { cvn } % \end{macrocode} % \end{macro} % % \subsection{Setting keys associated with label}\label{key:label} % % When \emph{tagged} \texttt{PDF} is active |\makelabel| is redefined using % |\makebox| to work correctly (\S\ref{env:item-starred-enumext}). From % the user side it is convenient to have a key that allows using this % redefinition with |\makebox| without having |\IfDocumentMetadataTF| active. % % \begin{macro}[int]{mode-box} % We define the key \mykey{mode-box} only for the \emph{\enquote{first level}} % of \myenv*{enumext} and \myenv*{enumext*} environments. % \iffalse %% Add |mode-box| key only on first level off |enumext| and |enumext*| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { mode-box .bool_set:N = \l_@@_mode_box_bool, mode-box .initial:n = false, mode-box .value_forbidden:n = true, } } \clist_map_inline:nn { level-1, enumext* } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{font, labelsep, labelwidth, wrap-label,wrap-label*} % Definition of keys \mykey{font}, \mykey{labelsep}, \mykey{labelwidth}, % \mykey{wrap-label} and \mykey{wrap-label*} keys for \myenv*{enumext} % and \myenv*{keyans} environments. % \iffalse %% Add |font|, |labelsep|, |labelwidth|, |wrap-label| and |wrap-label*| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { font .tl_set:c = { l_@@_label_font_style_#2_tl }, font .value_required:n = true, labelsep .dim_set:c = { l_@@_labelsep_#2_dim }, labelsep .initial:n = {0.3333em}, labelsep .value_required:n = true, labelwidth .dim_set:c = { l_@@_labelwidth_#2_dim }, labelwidth .value_required:n = true, wrap-label .cs_set_protected:cp = { @@_wrapper_label_#2:n } ##1, wrap-label .initial:n = {##1}, wrap-label .value_required:n = true, wrap-label* .code:n = { \bool_set_true:c { l_@@_wrap_label_opt_#2_bool } \keys_set:nn { enumext / #1 } { wrap-label = {##1} } }, wrap-label* .value_required:n = true, } } \clist_map_inline:Nn \c_@@_all_envs_clist { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{align} % The \mykey{align} key is implemented differently for \emph{\enquote{starred}} % and \emph{\enquote{non starred}} environments. For compatibility with % \emph{tagged} \texttt{PDF} we must set \myvarenv{l__@@_align_label_pos_X_str}. % \iffalse %% Add |align| key for |enumext| and |keyans| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { align .choice:, align / left .code:n = { \tl_clear:c { l_@@_label_fill_left_#2_tl } \tl_set:cn { l_@@_label_fill_right_#2_tl } { \hfill } \str_set:cn { l_@@_align_label_pos_#2_str } { l } }, align / right .code:n = { \tl_set:cn { l_@@_label_fill_left_#2_tl } { \hfill } \tl_clear:c { l_@@_label_fill_right_#2_tl } \str_set:cn { l_@@_align_label_pos_#2_str } { r } }, align / center .code:n = { \tl_set:cn { l_@@_label_fill_left_#2_tl } { \hfill } \tl_set:cn { l_@@_label_fill_right_#2_tl } { \hfill } \str_set:cn { l_@@_align_label_pos_#2_str } { c } }, align / unknown .code:n = \msg_error:nneee { enumext } { unknown-choice } { align } { left, ~ right, ~ center } { \exp_not:n {##1} }, align .initial:n = left, align .value_required:n = true, } } \clist_map_inline:nn { {level-1}{i}, {level-2}{ii}, {level-3}{iii}, {level-4}{iv}, {keyans}{v} } { \@@_tmp:nn #1 } % \end{macrocode} % \iffalse %% Add |align| key for |enummext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { align .choice:, align / left .code:n = \str_set:cn { l_@@_align_label_#2_str } { l }, align / right .code:n = \str_set:cn { l_@@_align_label_#2_str } { r }, align / center .code:n = \str_set:cn { l_@@_align_label_#2_str } { c }, align / unknown .code:n = \msg_error:nneee { enumext } { unknown-choice } { align } { left, ~ right, ~ center } { \exp_not:n {##1} }, align .initial:n = left, align .value_required:n = true, } } \clist_map_inline:nn { {enumext*}{vii}, {keyans*}{viii} } { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{label} and \texttt{ref} keys}\label{key:label-ref} % % The implementation of the keys \mykey{label} and \mykey{ref} are part % of the core of the package \mypkg*{enumext}, here the default values % for \mymeta{label}, the value of the variables \myvarenv{l__@@_label_X_tl}, % the default values for |\labelwidth| and the \emph{\enquote{label and ref}} system. % % \subsubsection{Define and set \texttt{label} and \texttt{ref} keys for \env{enumext} environment} % % \begin{macro}[int]{label,ref,\l_@@_label_i_tl,\l_@@_label_ii_tl, \l_@@_label_iii_tl, \l_@@_label_iv_tl} % Here we set the default \mymeta{labels} of the \emph{four levels} of % \myenv*{enumext} environment, along with the default value for % \mykey{labelwidth} key and \mykey{ref} key. % \iffalse %% Define and set |label| and |ref| keys for |enumext|. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nnn #1 #2 #3 { \keys_define:nn { enumext / #1 } { label .code:n = { \@@_label_style:cvn { l_@@_label_#2_tl } { l_@@_counter_#2_tl } {##1} \dim_set_eq:cN { l_@@_labelwidth_#2_dim } \l_@@_current_widest_dim }, label .initial:n = #3, label .value_required:n = true, ref .code:n = \@@_standar_ref:n {##1}, ref .value_required:n = true, } } \@@_tmp:nnn { level-1 } { i } { \arabic*.} \@@_tmp:nnn { level-2 } { ii } { (\alph*) } \@@_tmp:nnn { level-3 } { iii } { \roman*. } \@@_tmp:nnn { level-4 } { iv } { \Alph*. } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_standar_ref:n, \@@_standar_ref:,} % The \cs{@@_standar_ref:n} first we will pass the key argument to % \cs{l_@@_ref_key_arg_tl} and we will analyze its state, if it is not % \emph{empty} we will make a copy of the current counter in \cs{l_@@ _ref_the_count_tl} % and we will execute the function \cs{@@_regex_counter_style:} which % will return the modified \cs{l_@@_ref_key_arg_tl} and we make the % value of \cs{l_@@_ref_the_count_tl} the same as that \myvarenv{l__@@_the_counter_X_tl} % which contains |\theenumX| and finally we set \myvarenv{l__@@_renew_the_count_X_tl} % with the renewed command. % \iffalse %% Internal function used by |ref| key in enumext environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_standar_ref:n #1 { \tl_set:Nn \l_@@_ref_key_arg_tl {#1} \tl_if_empty:NTF \l_@@_ref_key_arg_tl { \msg_error:nnn { enumext } { key-ref-empty } { enumext } } { \tl_set_eq:Nc \l_@@_ref_the_count_tl { l_@@_counter_ \@@_level: _tl } \@@_regex_counter_style: \tl_set_eq:Nc \l_@@_ref_the_count_tl { l_@@_the_counter_ \@@_level: _tl } \tl_put_right:ce { l_@@_renew_the_count_ \@@_level: _tl } { \exp_not:N \renewcommand { \exp_not:V \l_@@_ref_the_count_tl } { \exp_not:V \l_@@_ref_key_arg_tl } } } } % \end{macrocode} % Finally the function \cs{@@_standar_ref:} will execute the % modification for the reference system in the second argument of the % environment definition \myenv*{enumext}. % \iffalse %% Activate |ref| key in second arg of list for |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_standar_ref: { \tl_if_empty:cF { l_@@_renew_the_count_ \@@_level: _tl } { \tl_use:c { l_@@_renew_the_count_ \@@_level: _tl } } } % \end{macrocode} % \end{macro} % % \subsubsection{Define and set \texttt{label} and \texttt{ref} keys for \env{enumext*} and \env{keyans*} environments} % % \begin{macro}[int]{label,ref, \l_@@_label_vii_tl, \l_@@_label_viii_tl} % Here we set the default \mymeta{labels} for \myenv*{enumext*} and % \myenv*{keyans*} environments, along with the default value for % \mykey{labelwidth} key and \mykey{ref} key. % \iffalse %% Define and set |label| and |ref| keys for starred environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nnn #1 #2 #3 { \keys_define:nn { enumext / #1 } { label .code:n = { \@@_label_style:cvn { l_@@_label_#2_tl } { l_@@_counter_#2_tl } {##1} \dim_set_eq:cN { l_@@_labelwidth_#2_dim } \l_@@_current_widest_dim }, label .initial:n = #3, label .value_required:n = true, ref .code:n = \@@_starred_ref:n {##1}, ref .value_required:n = true, } } \@@_tmp:nnn { enumext* } { vii } { \arabic*.} \@@_tmp:nnn { keyans* } { viii } { \Alph*) } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_starred_ref:n, \@@_starred_ref:} % The implementation of \cs{@@_starred_ref:n} is the same as that % used for the environment \myenv*{enumext}. % \iffalse %% Internal function used by |ref| key in |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_starred_ref:n #1 { \tl_set:Nn \l_@@_ref_key_arg_tl {#1} \int_compare:nNnT { \l_@@_level_h_int } = { 1 } { \tl_if_empty:NTF \l_@@_ref_key_arg_tl { \msg_error:nnn { enumext } { key-ref-empty } { enumext* } } { \tl_set_eq:NN \l_@@_ref_the_count_tl \l_@@_counter_vii_tl \@@_regex_counter_style: \tl_set_eq:NN \l_@@_ref_the_count_tl \l_@@_the_counter_vii_tl \tl_put_right:Ne \l_@@_renew_the_count_vii_tl { \exp_not:N \renewcommand { \exp_not:V \l_@@_ref_the_count_tl } { \exp_not:V \l_@@_ref_key_arg_tl } } } } \int_compare:nNnT { \l_@@_keyans_level_h_int } = { 1 } { \tl_if_empty:NTF \l_@@_ref_key_arg_tl { \msg_error:nnn { enumext } { key-ref-empty } { keyans* } } { \tl_set_eq:NN \l_@@_ref_the_count_tl \l_@@_counter_viii_tl \@@_regex_counter_style: \tl_set_eq:NN \l_@@_ref_the_count_tl \l_@@_the_counter_viii_tl \tl_put_right:Ne \l_@@_renew_the_count_viii_tl { \exp_not:N \renewcommand { \exp_not:V \l_@@_ref_the_count_tl } { \exp_not:V \l_@@_ref_key_arg_tl } } } } } % \end{macrocode} % Finally the function \cs{@@_starred_ref:} will execute the % modification for the reference system in the second argument of the % \myenv*{enumext*} and \myenv*{keyans*} environment definition. % \iffalse %% Activate |ref| key in second arg of list for |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_starred_ref: { \int_compare:nNnT { \l_@@_level_h_int } = { 1 } { \tl_if_empty:NF \l_@@_renew_the_count_vii_tl { \tl_use:N \l_@@_renew_the_count_vii_tl } } \int_compare:nNnT { \l_@@_keyans_level_h_int } = { 1 } { \tl_if_empty:NF \l_@@_renew_the_count_viii_tl { \tl_use:N \l_@@_renew_the_count_viii_tl } } } % \end{macrocode} % \end{macro} % % \subsubsection{Define and set \texttt{label} and \texttt{ref} keys for \env{keyans} and \env{keyanspic} environments} % % \begin{macro}[int]{label, ref} % \begin{macro}{\l_@@_label_v_tl,\l_@@_label_vi_tl,} % Here we set the default \mymeta{label} for \myenv*{keyans} % and \myenv*{keyanspic} environment, along with the default value for % \mykey{labelwidth} and \mykey{ref} key. The \myenv*{keyanspic} % environment use the same \mymeta{label} as the \myenv*{keyans} % environment. % \iffalse %% Define and set |label| and |ref| keys for |keyans| and |keyanspic|. % \fi % \begin{macrocode} \keys_define:nn { enumext / keyans } { label .code:n = { \@@_label_style:cvn { l_@@_label_v_tl } { l_@@_counter_v_tl } {#1} \dim_set_eq:cN { l_@@_labelwidth_v_dim } \l_@@_current_widest_dim \@@_label_style:cvn { l_@@_label_vi_tl } { l_@@_counter_vi_tl } {#1} \dim_set_eq:cN { l_@@_labelwidth_v_dim } \l_@@_current_widest_dim }, label .initial:n = \Alph*), label .value_required:n = true, ref .code:n = \@@_keyans_ref:n {#1}, ref .value_required:n = true, } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\@@_keyans_ref:n, \@@_keyans_ref:} % The implementation of \cs{@@_keyans_ref:n} is the same as that % used for the environment \myenv*{enumext}. % \iffalse %% Internal function used by |ref| key in |keyans| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_ref:n #1 { \tl_set:Nn \l_@@_ref_key_arg_tl {#1} \tl_if_empty:NTF \l_@@_ref_key_arg_tl { \msg_error:nnn { enumext } { key-ref-empty } { keyans } } { \tl_set_eq:NN \l_@@_ref_the_count_tl \l_@@_counter_v_tl \@@_regex_counter_style: \tl_set_eq:NN \l_@@_ref_the_count_tl \l_@@_the_counter_v_tl \tl_put_right:Ne \l_@@_renew_the_count_v_tl { \exp_not:N \renewcommand { \exp_not:V \l_@@_ref_the_count_tl } { \exp_not:V \l_@@_ref_key_arg_tl } } } } % \end{macrocode} % Finally the function \cs{@@_keyans_ref:} will execute the % modification for the reference system in the second argument of the % \myenv*{keyans*} environment definition. % \iffalse %% Activate |ref| key in second arg of list for |keyans| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_ref: { \tl_if_empty:NF \l_@@_renew_the_count_v_tl { \tl_use:N \l_@@_renew_the_count_v_tl } } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{start}, \texttt{start*} and \texttt{widest} keys}\label{key:start-widest} % % \begin{macro}{\@@_start_from:NNn, \@@_start_from:ccn, \@@_start_from:cce,} % The function \cs{@@_start_from:NNn} used by \mykey{start} and \mykey{start*} % keys take three arguments: % % \begin{arguments} % \item \myvarenv{l__@@_label_X_tl} % \item \myvarenv{l__@@_start_X_int} % \item \meta{integer or string} % \end{arguments} % % The first argument of this function are the \emph{\enquote{counter style}} set by % \mykey{label} key, the second argument is returned by the function, % the third argument can be an \mymeta{integer} or \mymeta{string} of the % form \ics{Alph}, \ics{alph}, \ics{Roman} or \ics{roman}. % This effectively allows \mykey{start}|=A| or \mykey{start}|=1| to % be used. % \iffalse %% Internal function for |start| key. %% #1 \l_enumext_label_X_tl %% #2 \l_enumext_start_X_int %% #3 integer or string % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_start_from:NNn #1 #2 #3 { \@@_if_is_int:nTF { #3 } { \int_set:Nn #2 {#3} } { \regex_match:nVT { \c{Alph} | \c{alph} } {#1} { \int_set:Nn #2 { \int_from_alph:n {#3} } } \regex_match:nVT { \c{Roman} | \c{roman} } {#1} { \int_set:Nn #2 { \int_from_roman:n {#3} } } } } \cs_generate_variant:Nn \@@_start_from:NNn { ccn, cce } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_widest_from:nNNn, \@@_widest_from:nccn} % The function \cs{@@_widest_from:nNNn} used by the \mykey{widest} % key take four arguments: % % \begin{arguments} % \item The counter associated with the environment level % \item \myvarenv{l__@@_label_X_tl} % \item \myvarenv{l__@@_labelwidth_X_dim} % \item \meta{integer or string} % \end{arguments} % % The second and third arguments of this function are the values set by % \mykey{label} and \mykey{labelwidth} keys, the four argument can % be an \mymeta{integer} or \mymeta{string} of the % form \ics{Alph}, \ics{alph}, \ics{Roman} or \ics{roman}. % The value of the four argument is set temporarily for the % identified counter in this point (level), then the value is expanded % into a \emph{\enquote{box}} and the \emph{\enquote{width}} of the % \emph{\enquote{box}} is returned. % \iffalse %% Internal function for |widest| key. %% #1 The counter associated with the environment level %% #2 \l_enumext_label_X_tl %% #3 \l_enumext_labelwidth_X_tl %% #4 integer or string % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_widest_from:nNNn #1 #2 #3 #4 { \@@_if_is_int:nTF {#4} { \setcounter{enumX#1} { #4 } } { \regex_match:nVT { \c{Alph} | \c{alph} } {#2} { \setcounter{enumX#1} { \int_from_alph:n {#4} } } \regex_match:nVT { \c{Roman} | \c{roman} } {#2} { \setcounter{enumX#1} { \int_from_roman:n {#4} } } } \@@_label_width_by_box:cv { l_@@_labelwidth_#1_dim } { l_@@_label_#1_tl } } \cs_generate_variant:Nn \@@_widest_from:nNNn { nccn } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{start, start*, widest,} % Now define and set \mykey{start*}, \mykey{start} and \mykey{widest} % keys for \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and % \myenv*{keyans*} environments. % % \iffalse %% Add |start*|, |start| and |widest| key. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { start* .code:n = { \@@_start_from:ccn { l_@@_label_#2_tl } { l_@@_start_#2_int } {##1} }, start* .value_required:n = true, start .code:n = { \@@_start_from:cce { l_@@_label_#2_tl } { l_@@_start_#2_int } { \int_eval:n {##1} } }, start .initial:n = 1, start .value_required:n = true, widest .code:n = { \@@_widest_from:nccn {#2} { l_@@_label_#2_tl } { l_@@_labelwidth_#2_dim } {##1} }, widest .value_required:n = true, } } \clist_map_inline:Nn \c_@@_all_envs_clist { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \subsection{Setting keys for vertical spaces} % % \begin{macro}[int]{topsep, partopsep, parsep, noitemsep, nosep} % Define and set \mykey{topsep}, \mykey{partopsep}, \mykey{parsep}, % \mykey{itemsep}, \mykey{noitemsep} and \mykey{nosep} keys for % \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and % \myenv*{keyans*} environments. % % \iffalse %% Add |topsep|, |partopsep|, |parsep|, |noitemsep| and |nosep| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nnnnnn #1 #2 #3 #4 #5 #6 { \keys_define:nn { enumext / #1 } { topsep .skip_set:c = { l_@@_topsep_#2_skip }, topsep .initial:n = {#3}, topsep .value_required:n = true, partopsep .skip_set:c = { l_@@_partopsep_#2_skip }, partopsep .initial:n = {#4}, partopsep .value_required:n = true, parsep .skip_set:c = { l_@@_parsep_#2_skip }, parsep .initial:n = {#5}, parsep .value_required:n = true, itemsep .skip_set:c = { l_@@_itemsep_#2_skip }, itemsep .initial:n = {#6}, itemsep .value_required:n = true, noitemsep .meta:n = { itemsep = 0pt, parsep = 0pt }, noitemsep .value_forbidden:n = true, nosep .meta:n = { itemsep = 0pt, parsep= 0pt, topsep = 0pt, partopsep = 0pt, }, nosep .value_forbidden:n = true, } } % \end{macrocode} % Now we set the values based on standard \myclass{article} class in % \mydim{10pt}. % \begin{macrocode} \@@_tmp:nnnnnn { level-1 } { i } { 8.0pt plus 2.0pt minus 4.0pt } { 2.0pt plus 1.0pt minus 1.0pt } { 4.0pt plus 2.0pt minus 1.0pt } { 4.0pt plus 2.0pt minus 1.0pt } \@@_tmp:nnnnnn { level-2 } { ii } { 4.0pt plus 2.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt } \@@_tmp:nnnnnn { level-3 } { iii } { 2.0pt plus 1.0pt minus 1.0pt } { 1.0pt minus 1.0pt }{ 0pt }{ 2.0pt plus 1.0pt minus 1.0pt } \@@_tmp:nnnnnn { level-4 } { iv } { 2.0pt plus 1.0pt minus 1.0pt } { 1.0pt minus 1.0pt }{ 0pt }{ 2.0pt plus 1.0pt minus 1.0pt } \@@_tmp:nnnnnn { keyans } { v }{ 4.0pt plus 2.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt }{ 2.0pt plus 1.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt } \@@_tmp:nnnnnn { enumext* } { vii } { 8.0pt plus 2.0pt minus 4.0pt } { 2.0pt plus 1.0pt minus 1.0pt } { 4.0pt plus 2.0pt minus 1.0pt } { 4.0pt plus 2.0pt minus 1.0pt } \@@_tmp:nnnnnn { keyans* } { viii } { 4.0pt plus 2.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt } { 2.0pt plus 1.0pt minus 1.0pt } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{base-fix} key}\label{key:base-fix} % % When nesting starting right after |\item| (without material between them) there % is a problem with the alignment of the \emph{baseline} between the two environments. % One way to get around this problem is to place |\mode_leave_vertical:| % apply |\vspace{-\baselineskip}| and set |\topsep=|\mydim{0pt} for % the \emph{\enquote{first level}} of the nested \myenv*{enumext} environment. % % \begin{macro}[int]{base-fix, \@@_nested_base_line_fix:} % We define the key \mykey{base-fix} only for the \emph{\enquote{first level}} % of \myenv*{enumext} environment. % \iffalse %% Add |base-fix| key only on first level off |enumext| environment. % \fi % \begin{macrocode} \keys_define:nn { enumext / level-1 } { base-fix .bool_set:N = \l_@@_base_line_fix_bool, base-fix .initial:n = false, base-fix .value_forbidden:n = true, } % \end{macrocode} % The function \cs{@@_nested_base_line_fix:} passed to the \cs{@@_parse_keys:n} % function in the definition of the \myenv*{enumext} environment (\S\ref{env:enumext}) % will be responsible for applying the \emph{baseline correction} and % adjusting the \mymeta{keys} for the \myenv*{enumext} environment and % the |\printkeyans| with \emph{starred argument} ‘|*|’ (\S\ref{cmd:printkeyans}). % % We will first implement the function code from the user side of the % \mykey{base-fix} key, that is, only the user knows when it is necessary % to apply it within the document in which case the variable % \cs{l_@@_print_keyans_star_bool} set by the |\printkeyans| command is % false and the variable \cs{l_@@_base_line_fix_bool} is true. % \iffalse %% Internal function for |base-fix| key in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_nested_base_line_fix: { \bool_lazy_all:nT { { \bool_if_p:N \l_@@_starred_first_bool } { \bool_if_p:N \l_@@_base_line_fix_bool } { \bool_not_p:n { \l_@@_print_keyans_star_bool } } } { \mode_leave_vertical: \vspace { -\dim_eval:n { \baselineskip + \parsep } } } % \end{macrocode} % When we are running the |\printkeyans| command with the \emph{starred % argument} ‘|*|’ the variable \cs{l_@@_print_keyans_star_bool} is true % and we can run a simplified version of |\vspace| using |\skip_vertical:n|. % \begin{macrocode} \bool_lazy_and:nnT { \bool_if_p:N \l_@@_starred_first_bool } { \bool_if_p:N \l_@@_print_keyans_star_bool } { \mode_leave_vertical: \skip_vertical:n { -\baselineskip } \skip_vertical:N \c_zero_skip } % \end{macrocode} % Finally we set the values ​​of the keys \mykey{topsep}, \mykey{above} % and \mykey{above*} for the \emph{\enquote{first level}} of \myenv*{enumext} % environment equal to \mydim{0pt} and set the variable \cs{l_@@_base_line_fix_bool} % to false. % \begin{macrocode} \keys_set:nn { enumext / level-1 } { topsep = 0pt, above = 0pt, above* = 0pt, } \bool_set_false:N \l_@@_base_line_fix_bool } % \end{macrocode} % \end{macro} % % \subsection{Setting keys for horizontal spaces}\label{key:list-indent} % % \begin{macro}[int]{itemindent, rightmargin, listparindent, list-offset, list-indent} % Define and set \mykey{itemindent}, \mykey{rightmargin}, \mykey{listparindent}, \mykey{list-offset} % and \mykey{list-indent} keys for \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and % \myenv*{keyans*} environments. % \iffalse %% Add |itemindent|, |rightmargin|, |listparindent|, |list-offset| and |list-indent| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { itemindent .dim_set:c = { l_@@_fake_item_indent_#2_dim }, itemindent .value_required:n = true, rightmargin .dim_set:c = { l_@@_rightmargin_#2_dim }, rightmargin .value_required:n = true, listparindent .dim_set:c = { l_@@_listparindent_#2_dim }, listparindent .value_required:n = true, list-offset .dim_set:c = { l_@@_listoffset_#2_dim }, list-offset .value_required:n = true, list-indent .code:n = \bool_set_true:c { l_@@_leftmargin_tmp_#2_bool } \dim_set:cn { l_@@_leftmargin_tmp_#2_dim } {##1}, list-indent .value_required:n = true, } } \clist_map_inline:nn { {level-1}{i}, {level-2}{ii}, {level-3}{iii}, {level-4}{iv}, {keyans}{v} } { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % For \myenv*{enumext*} and \myenv*{keyans*} environments the situation % is a bit different, the \mykey{list-indent} key behaves like the \mykey{list-offset} key. % \iffalse %% Set |list-offset| and |list-indent| keys for |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { itemindent .dim_set:c = { l_@@_fake_item_indent_#2_dim }, itemindent .value_required:n = true, rightmargin .dim_set:c = { l_@@_rightmargin_#2_dim }, rightmargin .value_required:n = true, listparindent .dim_set:c = { l_@@_listparindent_#2_dim }, listparindent .value_required:n = true, list-offset .dim_set:c = { l_@@_listoffset_#2_dim }, list-offset .value_required:n = true, list-indent .meta:n = { list-offset = ##1 }, list-indent .value_required:n = true, } } \clist_map_inline:nn { {enumext*}{vii}, {keyans*}{viii} } { \@@_tmp:nn #1 } % \end{macrocode} % % \subsubsection{Functions for setting the fake \texttt{itemindent}}\label{key:fake-indent} % % \begin{macro}[int]{\@@_fake_item_indent:,\@@_keyans_fake_item_indent:, % \@@_fake_item_indent_vii:, \@@_fake_item_indent_viii:,} % % The \mykey{itemindent} key does not set the value of |\itemindent|, it only % sets the value of the \emph{horizontal space} applied using |\skip_horizontal:N|. We will % store this value in the variable and only apply it when it is greater % than \mydim{0pt}. Here I will need to place % |\mode_leave_vertical:| and the plain \hologo{TeX} macro % |\ignorespaces| to avoid unwanted extra space when using the % \mykey{itemindent} key. % \iffalse %% Internal functions for |itemindent| key. |\mode_leave_vertical:| nor % \fi % \begin{macrocode} \cs_set_protected:Nn \@@_fake_item_indent: { \dim_compare:nNnT { \dim_use:c { l_@@_fake_item_indent_ \@@_level: _dim } } > { \c_zero_dim } { \tl_set:ce { l_@@_fake_item_indent_ \@@_level: _tl } { \exp_not:N \mode_leave_vertical: \exp_not:n { \skip_horizontal:n } { \dim_use:c { l_@@_fake_item_indent_ \@@_level: _dim } } \exp_not:N \ignorespaces } } } \cs_set_protected:Nn \@@_keyans_fake_item_indent: { \dim_compare:nNnT { \l_@@_fake_item_indent_v_dim } > { \c_zero_dim } { \tl_set:Ne \l_@@_fake_item_indent_v_tl { \exp_not:N \mode_leave_vertical: \exp_not:N \skip_horizontal:N \l_@@_fake_item_indent_v_dim \exp_not:N \ignorespaces } } } \cs_set_protected:Nn \@@_fake_item_indent_vii: { \dim_compare:nNnT { \l_@@_fake_item_indent_vii_dim } > { \c_zero_dim } { \tl_set:Ne \l_@@_fake_item_indent_vii_tl { \exp_not:N \skip_horizontal:N \l_@@_fake_item_indent_vii_dim \exp_not:N \ignorespaces } } } \cs_set_protected:Nn \@@_fake_item_indent_viii: { \dim_compare:nNnT { \l_@@_fake_item_indent_viii_dim } > { \c_zero_dim } { \tl_set:Ne \l_@@_fake_item_indent_viii_tl { \exp_not:N \skip_horizontal:N \l_@@_fake_item_indent_viii_dim \exp_not:N \ignorespaces } } } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{show-length} key} % % \begin{macro}[int]{show-length} % Define and set \mykey{show-length} key for \myenv*{enumext}, % \myenv*{enumext*}, \myenv*{keyans} and \myenv*{keyans*} environments. % The function sets the boolean variable \myvarenv{l__@@_show_length_X_bool} % used in the definition of all environments to \emph{\enquote{true}} % and calls the function \cs{@@_show_length:nnn} which prints all the % values of the \emph{\enquote{vertical}} and \emph{\enquote{horizontal}} % parameters calculated and used. % \iffalse %% Add |show-length| key for all environments.. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { show-length .bool_set:c = { l_@@_show_length_#2_bool }, show-length .initial:n = false, } } \clist_map_inline:Nn \c_@@_all_envs_clist { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{before}, \texttt{after} and \texttt{first} keys}\label{key:before} % % \begin{macro}[int]{before, before*, after, first} % Define and set \mykey{before}, \mykey{before*}, \mykey{after} and \mykey{first} keys % for \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and \myenv*{keyans*} environments. % \iffalse %% Add |before|, |before*|, |after| and |first| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { before .tl_set:c = { l_@@_before_no_starred_key_#2_tl }, before .value_required:n = true, before* .tl_set:c = { l_@@_before_starred_key_#2_tl }, before* .value_required:n = true, after .tl_set:c = { l_@@_after_stop_list_#2_tl }, after .value_required:n = true, first .tl_set:c = { l_@@_after_list_args_#2_tl }, first .value_required:n = true, } } \clist_map_inline:Nn \c_@@_all_envs_clist { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for \texttt{before}, \texttt{after} and \texttt{first} keys in \env{enumext}} % % \begin{macro}{\@@_before_args_exec:,\@@_before_keys_exec:, % \@@_after_stop_list:,\@@_after_args_exec:,} % The function \cs{@@_before_args_exec:} executes the \mymarg{code} set by the % \mykey{before*} key \emph{\enquote{before}} the \myenv*{enumext} % environment is started. The \mymarg{code} is executed \emph{\enquote{without}} % knowing any definition of the \mymarg{arg two} of the list: % \mymarg[cbc=pkgcolor,ac=araracolor]{code}|\list|\mymarg{arg one}\mymarg{arg two}. % \iffalse %% Function for |before|, |before*|, |after| and |first| keys in |enumext|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_before_args_exec: { \tl_use:c { l_@@_before_starred_key_ \@@_level: _tl } } % \end{macrocode} % The function \cs{@@_before_keys_exec:} executes the \mymarg{code} set by the % \mykey{before} key \emph{\enquote{before}} the \myenv*{enumext} % environment is started in \emph{second argument} of the list. The % \mymarg{code} is executed \emph{\enquote{knowing}} % all definition and values provides by \mymeta{keys}: % |\list|\mymarg{arg one}|{|\mymeta{arg two}\mymarg[cbc=pkgcolor,ac=araracolor]{code}|}| % \begin{macrocode} \cs_new_protected:Nn \@@_before_keys_exec: { \tl_use:c { l_@@_before_no_starred_key_ \@@_level: _tl } } % \end{macrocode} % The function \cs{@@_after_stop_list:} executes the \mymarg{code} set by the % \mykey{after} key \emph{\enquote{after}} the \myenv*{enumext} % environment has finished: |\endlist|\mymarg[cbc=pkgcolor,ac=araracolor]{code}. % \begin{macrocode} \cs_new_protected:Nn \@@_after_stop_list: { \tl_use:c { l_@@_after_stop_list_ \@@_level: _tl } } % \end{macrocode} % The function \cs{@@_after_args_exec:} executes the \mymarg{code} set by the % \mykey{first} key after the end of the second argument of the list % defining the \myenv*{enumext} environment, just before the first % occurrence of |\item|: |\list|\mymarg{arg one}\mymarg{arg two}\mymarg[cbc=pkgcolor,ac=araracolor]{code}|\item|. % \begin{macrocode} \cs_new_protected:Nn \@@_after_args_exec: { \tl_use:c { l_@@_after_list_args_ \@@_level: _tl } } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for \texttt{before}, \texttt{after} and \texttt{first} keys in \env{keyans}} % % \begin{macro}{\@@_before_args_exec_v:,\@@_before_keys_exec_v:, % \@@_after_stop_list_v:, \@@_after_args_exec_v:} % Same implementation as the one used in the \myenv*{enumext} environment. % \iffalse %% Function for |before|, |before*|, |after| and |first| keys in |keyans|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_before_args_exec_v: { \tl_use:N \l_@@_before_starred_key_v_tl } \cs_new_protected:Nn \@@_before_keys_exec_v: { \tl_use:N \l_@@_before_no_starred_key_v_tl } \cs_new_protected:Nn \@@_after_stop_list_v: { \tl_use:N \l_@@_after_stop_list_v_tl } \cs_new_protected:Nn \@@_after_args_exec_v: { \tl_use:N \l_@@_after_list_args_v_tl } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for \texttt{before}, \texttt{after} and \texttt{first} keys in \env{enumext*} and \env{keyans*}} % % \begin{macro}{\@@_before_args_exec_vii:,\@@_before_keys_exec_vii, % \@@_after_stop_list_vii:, \@@_after_args_exec_vii:,} % Same implementation as the one used in the \myenv*{enumext} environment. % \iffalse %% Function for |before|, |before*|, |after| and |first| keys in |enumext*| and |keyans*|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_before_args_exec_vii: { \tl_use:N \l_@@_before_starred_key_vii_tl } \cs_new_protected:Nn \@@_before_args_exec_viii: { \tl_use:N \l_@@_before_starred_key_viii_tl } \cs_new_protected:Nn \@@_before_keys_exec_vii: { \tl_use:N \l_@@_before_no_starred_key_vii_tl } \cs_new_protected:Nn \@@_before_keys_exec_viii: { \tl_use:N \l_@@_before_no_starred_key_viii_tl } \cs_new_protected:Nn \@@_after_stop_list_vii: { \tl_use:N \l_@@_after_stop_list_vii_tl } \cs_new_protected:Nn \@@_after_stop_list_viii: { \tl_use:N \l_@@_after_stop_list_viii_tl } \cs_new_protected:Nn \@@_after_args_exec_vii: { \tl_use:N \l_@@_after_list_args_vii_tl } \cs_new_protected:Nn \@@_after_args_exec_viii: { \tl_use:N \l_@@_after_list_args_viii_tl } % \end{macrocode} % \end{macro} % % \subsection{Setting keys for \env{multicols} and \env{minipage}}\label{key:mini-multi} % % \begin{macro}[int]{mini-env, mini-sep, columns-sep, columns} % The default value of the \mykey{columns-sep} key is handled by % the state of the boolean variable \myvarenv{l__@@_columns_sep_X_bool} % which is handled in the internal definition of the \myenv*{enumext} % and \myenv*{keyans} environments. % Define and set \mykey{mini-env}, \mykey{mini-sep}, \mykey{columns-sep} % and \mykey{columns} keys for \myenv*{enumext}, \myenv*{enumext*}, \myenv*{keyans} and % \myenv*{keyans*} environments. % \iffalse %% Add |mini-env|, |mini-sep|, |columns-sep| and |columns| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { mini-env .dim_set:c = { l_@@_minipage_right_#2_dim }, mini-env .value_required:n = true, mini-sep .dim_set:c = { l_@@_minipage_hsep_#2_dim }, mini-sep .initial:n = 0.3333em, mini-sep .value_required:n = true, columns-sep .dim_set:c = { l_@@_columns_sep_#2_dim }, columns-sep .value_required:n = true, columns .int_set:c = { l_@@_columns_#2_int }, columns .initial:n = 1, columns .value_required:n = true, } } \clist_map_inline:Nn \c_@@_all_envs_clist { \@@_tmp:nn #1 } % \end{macrocode} % % For \myenv*{enumext*} and \myenv*{keyans*} environments the situation % is a bit different, the command \ics*{miniright} is not available, so we will add % the keys \mykey{mini-right} and \mykey{mini-right*} to implement support for % \myenv{minipage} environment. % \iffalse %% Add |mini-right| and |mini-right*| keys for starred environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { mini-right .tl_gset:c = { g_@@_miniright_code_#2_tl }, mini-right .value_required:n = true, mini-right* .code:n = { \bool_gset_true:c { g_@@_minipage_center_#2_bool } \keys_set:nn { enumext / #1 } { mini-right = {##1} } }, mini-right* .value_required:n = true, } } \clist_map_inline:nn { {enumext*}{vii}, {keyans*}{viii} } { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \subsection{Adjustment of vertical spaces for \env{multicols}} \label{vspace:multi} % % When nesting a \emph{\enquote{list environment}} inside the \myenv{multicols} environment, % the values of the \emph{\enquote{vertical spaces}} are lost, basically the % \myenv{multicols} environment takes control over them. Graphically it can % be seen like in the figure \ref{fig:six}. % % \begin{figure}[!htbp] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[color=white] (7.0,6.10) rectangle (17.5,6.50) node[pos=.5,text=black] { \textcolor{blue}{\texttt{\textbackslash{}multicolsep [±\textbackslash{}topskip]}} };% space above % \draw[color=white] (7.0,4.85) rectangle (17.5,5.25) node[pos=.5,text=black] { \textcolor{blue}{\texttt{\textbackslash{}multicolsep [±\textbackslash{}prevdepth?]}} };% space below % \draw[color=white] (2.0,6.10) rectangle (5,6.50) node[pos=.5,text=optcolor,font=\footnotesize\ttfamily] { topsep };% topsep above % \draw[color=white] (2.0,4.85) rectangle (5,5.25) node[pos=.5,text=optcolor,font=\footnotesize\ttfamily] { topsep };% topsep below % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=optcolor]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[->,color=lightgray,shorten >=3pt] (4.5,6.3) -- (7.0,6.3); % glue space = topsep (above) % \draw[->,color=lightgray,shorten >=3pt] (4.5,5.05) -- (7.0,5.05); % glue space = topsep (above) % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (17.5,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.25) rectangle (11.5,6.10) node[pos=.5,text=black] % {\begin{tabular}{c} % \texttt{column one} \\ % \textcolor{blue}{\emph{nested list or items}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (13.5,5.25) rectangle (17.5,6.10) node[pos=.5,text=black] % {\begin{tabular}{c} % \texttt{column two} \\ % \textcolor{blue}{\emph{nested list or items}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,4.5) rectangle (5.0,4.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,4.5) rectangle (7.0,4.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,4.5) rectangle (17.5,4.85);% item width % \end{tikzpicture} % \caption{Representation of the vertical space in \myenv{multicols} for a nested level.} % \label{fig:six} % \end{figure} % % To keep the desired spaces \emph{above} and \emph{below} in the \emph{\enquote{list environment}} % (|\topsep + [\partopsep]|) it is necessary to \emph{\enquote{adjust}} the spaces added % by the \myenv{multicols} environment. % The most appropriate option in this case is to use a \emph{\enquote{context sensitive}} % vertical space with |\addvspace|. % % \smallskip % % \begin{important}* % I should make it clear that the implementation here is a \emph{\enquote{bit % questionable}}. At first glance doing |\multicolsep=\topsep| seemed right, but the results % were not always as expected. An almost \emph{imperceptible} detail is that in some cases the % |\itemsep| values of are \emph{\enquote{stretched}}, possibly due to % the use of |\raggedcolumns| and this affects the lower space when % closing the environment, which is \emph{\enquote{smaller}} than % expected. My attempts to find the correct values using |\showoutput| and % |\showboxdepth| absolutely failed. % \end{important} % % \subsubsection{Adjustment of vertical spaces for \env{multicols} in \env{enumext}} % % % \begin{macro}{\@@_multi_set_vskip:} % The function \cs{@@_multi_set_vskip:} will take care of determining the % \emph{\enquote{adjusted spaces}} that we will apply \emph{\enquote{above}} and % \emph{\enquote{below}} the \myenv{multicols} environment in % \myenv*{enumext}. % % \smallskip % % We will set the default values taking into account that \hologo{TeX} is % in \mymeta{horizontal mode}, then we will make the settings for the % \mymeta{vertical mode} in which |\partopsep| comes into play. % % \smallskip % % Set the values of \myvarenv{l__@@_multicols_above_X_skip} and \myvarenv{l__@@_multicols_below_X_skip} % equal to the value of |\topsep| in the \emph{current level}. % \iffalse %% Adjustment of vertical spacing for |multicols| in |enumext|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_multi_set_vskip: { \skip_set:cn { l_@@_multicols_above_ \@@_level: _skip } { \skip_use:c { l_@@_topsep_ \@@_level: _skip } } \skip_set:cn { l_@@_multicols_below_ \@@_level: _skip } { \skip_use:c { l_@@_topsep_ \@@_level: _skip } } \@@_add_pre_parsep: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_pre_parsep:} % The function \cs{@@_add_pre_parsep:} \emph{\enquote{adjusted}} the value % of \myvarenv{l__@@_multicols_above_X_skip} detecting the value of % \ics{parsep} from the previous level. This is necessary since % \ics{parsep} from the previous level affects the \emph{vertical spaces}. % \iffalse %% Detect |\parsep| from previous level and adjust |\l_@@_multicols_above_X_skip| for |multicols| in |enumext|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_add_pre_parsep: { \int_case:nn { \l_@@_level_int } { { 2 }{ \skip_if_eq:nnF { \l_@@_parsep_i_skip } { \c_zero_skip } { \skip_add:Nn \l_@@_multicols_above_ii_skip { \l_@@_parsep_i_skip } } } { 3 }{ \skip_if_eq:nnF { \l_@@_parsep_ii_skip } { \c_zero_skip } { \skip_add:Nn \l_@@_multicols_above_iii_skip { \l_@@_parsep_ii_skip } } } { 4 }{ \skip_if_eq:nnF { \l_@@_parsep_iii_skip } { \c_zero_skip } { \skip_add:Nn \l_@@_multicols_above_iv_skip { \l_@@_parsep_iii_skip } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_multi_addvspace:} % The function \cs{@@_multi_addvspace:} will apply the spaces set using % |\addvspace| \emph{\enquote{above}} the \myenv{multicols} environment % in \myenv*{enumext}, taking into account whether \hologo{TeX} is in % \mymeta{horizontal mode} or \mymeta{vertical mode}. % \iffalse %% Add vertical spacing for |multicols| in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_multi_addvspace: { \@@_multi_set_vskip: \mode_if_vertical:T { \skip_add:cn { l_@@_multicols_above_ \@@_level: _skip } { \skip_use:c { l_@@_partopsep_ \@@_level: _skip } } \skip_add:cn { l_@@_multicols_below_ \@@_level: _skip } { \skip_use:c { l_@@_partopsep_ \@@_level: _skip } } } \par\nopagebreak \addvspace{ \skip_use:c { l_@@_multicols_above_ \@@_level: _skip } } } % \end{macrocode} % \end{macro} % % \subsubsection{Adjustment of vertical spaces for \env{multicols} in \env{keyans}} % % \begin{macro}{\@@_keyans_multi_set_vskip:, \@@_keyans_multi_addvspace:} % The function \cs{@@_keyans_multi_set_vskip:} will take care of determining the % \emph{\enquote{adjusted spaces}} that we will apply \emph{\enquote{above}} and % \emph{\enquote{below}} the \myenv{multicols} environment in % \myenv*{keyans}. The implementation of this function is the same % as the one used in \myenv*{enumext}. % \iffalse %% Adjustment of vertical spacing for |multicols| in |keyans| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_multi_set_vskip: { \skip_set:Nn \l_@@_multicols_above_v_skip { \l_@@_topsep_v_skip } \skip_set:Nn \l_@@_multicols_below_v_skip { \l_@@_topsep_v_skip } } \cs_new_protected:Nn \@@_keyans_multi_addvspace: { \@@_keyans_multi_set_vskip: \mode_if_vertical:T { \skip_add:Nn \l_@@_multicols_above_v_skip { \skip_use:N \l_@@_partopsep_v_skip } \skip_add:Nn \l_@@_multicols_below_v_skip { \skip_use:N \l_@@_partopsep_v_skip } } \par\nopagebreak \addvspace{ \l_@@_multicols_above_v_skip } } % \end{macrocode} % \end{macro} % % \subsection{Adjustment of vertical spaces for \env{minipage}}\label{vspace:minipage} % % When nesting a \emph{\enquote{list environment}} within the \myenv{minipage} environment, % the values of the \emph{\enquote{vertical spaces}} are lost. Graphically it can % be seen like in the figure \ref{fig:seven}. % % \begin{figure}[!htbp] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[color=white] (7.0,6.10) rectangle (12.5,6.5) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{space above left}} };% space above left % \draw[color=white] (13.5,6.10) rectangle (17.5,6.5) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{space above right}} };% space above right % \draw[color=white] (7.0,4.85) rectangle (17.5,5.25) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{space below minipage's}} };% space below after second % \draw[color=white] (2.0,6.10) rectangle (5,6.50) node[pos=.5,text=optcolor,font=\footnotesize\ttfamily] { topsep };% topsep above % \draw[color=white] (2.0,4.85) rectangle (5,5.25) node[pos=.5,text=optcolor,font=\footnotesize\ttfamily] { topsep };% topsep below % \draw[->,color=lightgray,shorten >=3pt] (4.5,6.3) -- (7.0,6.3); % glue space = topsep (above) % \draw[->,color=lightgray,shorten >=3pt] (4.5,5.05) -- (7.0,5.05); % glue space = topsep (above) % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=optcolor]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (17.5,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.25) rectangle (12.5,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage left [t]} \\ % \textcolor{blue}{\emph{nested list}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (13.5,5.25) rectangle (17.5,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage right [t]} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,4.5) rectangle (5.0,4.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,4.5) rectangle (7.0,4.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,4.5) rectangle (17.5,4.85);% item width % \end{tikzpicture} % \caption{Representation of the \myenv{minipage} spacing adjustment for a nested level.} % \label{fig:seven} % \end{figure} % % Since we want to keep the \emph{\enquote{left}} and \emph{\enquote{right}} % environments \emph{\enquote{aligned on top}}, preserving the \ics{baselineskip} % and keep the desired \emph{\enquote{spaces}} (|\topsep + [\partopsep]|) it is necessary % to \emph{\enquote{adjust}} the \emph{\enquote{vertical spaces}} % for \myenv{minipage} environments. % % \smallskip % % Here there are several complications that we must circumvent, the % \myenv{minipage} environment eliminates the \enquote{top} spaces, the \myenv{multicols} % environment can be nested in the \myenv{minipage} environment, the \enquote{top} and % \enquote{bottom} spaces are affected when |topsep=|\mydim{0pt} and to this is added the % |\partopsep| parameter that comes into action according to whether \hologo{TeX} % is in \mymeta{horizontal mode} or \mymeta{vertical mode}. Depending on these cases, small % adjustments must be made using |\vspace| and |\addvspace| to % obtain the \emph{\enquote{desired vertical spacing}}. % % \smallskip % % \begin{important}* % Again I must make clear that the implementation here is a \emph{\enquote{bit % questionable}}, but hunting the spaces (|glue|) produced by the \myenv{minipage} % environment is quite complicated, even more if \myenv{multicols} it is nested. % The setting of the values was more \emph{\enquote{trial and error}} % (aprox to |\strutbox|), using the help of the \mypkg{lua-visual-debug}\cite{luavisual} % package, again my attempts to find the correct values using |\showoutput| and % |\showboxdepth| absolutely failed. % \end{important} % % \subsubsection{Adjustment of vertical spaces for \env{minipage} in \env{enumext}} % % \begin{macro}{\@@_minipage_set_skip:, \@@_minipage_add_space:} % The function \cs{@@_minipage_set_skip:} will take care of determining the % \emph{\enquote{adjust}} spaces that we will apply \emph{\enquote{above}} and % \emph{\enquote{below}} the \myvarenv*{__@@_mini_page} environment in % \myenv*{enumext}. % % \smallskip % % First we will set the value of \cs{l_@@_minipage_right_skip} equal to % |\topsep|, then we will see if \hologo{TeX} is in \mymeta{vertical mode} and we % will add |\partopsep|, followed by that we set the value of \cs{l_@@_minipage_after_skip}. % \iffalse %% Adjustment of vertical spacing for |minipage| in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_minipage_set_skip: { \skip_set:Nn \l_@@_minipage_right_skip { \skip_use:c { l_@@_topsep_ \@@_level: _skip } } \mode_if_vertical:T { \skip_add:Nn \l_@@_minipage_right_skip { \skip_use:c { l_@@_partopsep_ \@@_level: _skip } } } \skip_set_eq:NN \l_@@_minipage_after_skip \l_@@_minipage_right_skip % \end{macrocode} % We will adjust the values ​​\cs[no-index]{l_@@_multicols_above_X_skip} % and \cs[no-index]{l_@@_multicols_below_X_skip} and call the function % \cs{@@_pre_itemsep_skip:}. % \begin{macrocode} \skip_set_eq:cN { l_@@_multicols_above_ \@@_level: _skip } \l_@@_minipage_right_skip \skip_set_eq:cN { l_@@_multicols_below_ \@@_level: _skip } \l_@@_minipage_right_skip \@@_pre_itemsep_skip: % \end{macrocode} % If the environment \myenv{multicols} is active, we set |\topskip=|\mydim{0pt} % and then we make |\multicolsep| have the same value as ​​\cs[no-index]{l_@@_multicols_above_X_skip}. % \begin{macrocode} \int_compare:nNnT { \int_use:c { l_@@_columns_ \@@_level: _int } } > { 1 } { \skip_zero:N \topskip \skip_set_eq:Nc \multicolsep { l_@@_multicols_above_ \@@_level: _skip } } } % \end{macrocode} % The function \cs{@@_minipage_add_space:} will apply the spaces on the \emph{\enquote{left side}} using % |\addvspace| \emph{\enquote{above}} the \myvarenv*{__@@_mini_page} % environment, taking into account whether \hologo{TeX} is in % \mymeta{horizontal mode} or \mymeta{vertical mode}. Here we use the plain \hologo{TeX} macro % |\nointerlineskip| to prevent baseline \emph{\enquote{glue}} being % added between the next pair of boxes in a \emph{vertical list}. For the latter we % will make some adjustments since the |\partopsep| parameter comes into % play and this affects the \emph{vertical spacing}. % \begin{macrocode} \cs_new_protected:Nn \@@_minipage_add_space: { \@@_minipage_set_skip: \@@_unskip_unkern: \mode_if_vertical:TF { \nopagebreak\nointerlineskip } { \par\nopagebreak\nointerlineskip \skip_zero:c { l_@@_partopsep_ \@@_level: _skip } } \int_compare:nNnTF { \int_use:c { l_@@_columns_ \@@_level: _int } } > { 1 } { \addvspace{ 0.445\box_ht:N \strutbox } } { \addvspace{ 0.250\box_ht:N \strutbox } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_pre_itemsep_skip:} % The function \cs{@@_pre_itemsep_skip:} will adjust the spaces below the % environment \myenv{minipage} and the environment \myenv{multicols} if % it is nested in it, taking into account the value of |\itemsep| from % the previous level. % \begin{macrocode} \cs_new_protected:Nn \@@_pre_itemsep_skip: { \int_case:nn { \l_@@_level_int } { { 2 }{ \skip_if_eq:nnTF { \l_@@_itemsep_i_skip } { \l_@@_minipage_after_skip } { \skip_set:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_set:Nn \l_@@_multicols_below_ii_skip { 0.350\box_ht:N \strutbox } } { \dim_compare:nNnT { \l_@@_itemsep_i_skip } < { \l_@@_minipage_after_skip } { \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_i_skip } \skip_sub:Nn \l_@@_multicols_below_ii_skip { \l_@@_itemsep_i_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_add:Nn \l_@@_multicols_below_ii_skip { 0.350\box_ht:N \strutbox } } \dim_compare:nNnT { \l_@@_itemsep_i_skip } > { \l_@@_minipage_after_skip } { \skip_set:Nn \l_@@_minipage_temp_skip { \l_@@_itemsep_i_skip - \l_@@_minipage_after_skip } \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_i_skip } \skip_sub:Nn \l_@@_multicols_below_ii_skip { \l_@@_itemsep_i_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox + \l_@@_minipage_temp_skip } \skip_add:Nn \l_@@_multicols_below_ii_skip { 0.350\box_ht:N \strutbox + \l_@@_minipage_temp_skip } } } } { 3 }{ \skip_if_eq:nnTF { \l_@@_itemsep_ii_skip } { \c_zero_skip } { \skip_set:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_set:Nn \l_@@_multicols_below_iii_skip { 0.350\box_ht:N \strutbox } } { \dim_compare:nNnT { \l_@@_itemsep_ii_skip } < { \l_@@_minipage_after_skip } { \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_ii_skip } \skip_sub:Nn \l_@@_multicols_below_iii_skip { \l_@@_itemsep_ii_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_add:Nn \l_@@_multicols_below_iii_skip { 0.350\box_ht:N \strutbox } } \dim_compare:nNnT { \l_@@_itemsep_ii_skip } > { \l_@@_minipage_after_skip } { \skip_set:Nn \l_@@_minipage_temp_skip { \l_@@_itemsep_ii_skip - \l_@@_minipage_after_skip } \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_ii_skip } \skip_sub:Nn \l_@@_multicols_below_iii_skip { \l_@@_itemsep_ii_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox + \l_@@_minipage_temp_skip } \skip_add:Nn \l_@@_multicols_below_iii_skip { 0.350\box_ht:N \strutbox + \l_@@_minipage_temp_skip } } } } { 4 }{ \skip_if_eq:nnTF { \l_@@_itemsep_iii_skip } { \c_zero_skip } { \skip_set:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_set:Nn \l_@@_multicols_below_iv_skip { 0.350\box_ht:N \strutbox } } { \dim_compare:nNnT { \l_@@_itemsep_iii_skip } < { \l_@@_minipage_after_skip } { \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_iii_skip } \skip_sub:Nn \l_@@_multicols_below_iv_skip { \l_@@_itemsep_iii_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_add:Nn \l_@@_multicols_below_iv_skip { 0.350\box_ht:N \strutbox } } \dim_compare:nNnT { \l_@@_itemsep_iii_skip } > { \l_@@_minipage_after_skip } { \skip_set:Nn \l_@@_minipage_temp_skip { \l_@@_itemsep_iii_skip - \l_@@_minipage_after_skip } \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_iii_skip } \skip_sub:Nn \l_@@_multicols_below_iv_skip { \l_@@_itemsep_iii_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox + \l_@@_minipage_temp_skip } \skip_add:Nn \l_@@_multicols_below_iv_skip { 0.350\box_ht:N \strutbox + \l_@@_minipage_temp_skip } } } } } } % \end{macrocode} % \end{macro} % % \subsubsection{Adjustment of vertical spaces for \env{minipage} in \env{keyans}} % % \begin{macro}{\@@_keyans_minipage_set_skip:, \@@_keyans_minipage_add_space:, \@@_keyans_pre_itemsep_skip:} % The function \cs{@@_keyans_mini_set_vskip:} will take care of determining the % \enquote{adjusted} spaces that we will apply \emph{\enquote{above}} and % \emph{\enquote{below}} the \myvarenv*{__@@_mini_page} environment in % \myenv*{keyans}. The implementation of this function is the same % as the one used in \myenv*{enumext}. % \iffalse %% Adjustment of vertical spacing for |minipage| in |keyans| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_minipage_set_skip: { \skip_zero:N \l_@@_minipage_after_skip \skip_zero:N \l_@@_minipage_left_skip \skip_zero:N \l_@@_minipage_right_skip \skip_set:Nn \l_@@_minipage_right_skip { \l_@@_topsep_v_skip } \mode_if_vertical:T { \skip_add:Nn \l_@@_minipage_right_skip { \l_@@_partopsep_v_skip } } \skip_set_eq:NN \l_@@_minipage_after_skip \l_@@_minipage_right_skip \skip_set_eq:NN \l_@@_multicols_above_v_skip \l_@@_minipage_right_skip \skip_set_eq:NN \l_@@_multicols_below_v_skip \l_@@_minipage_right_skip \@@_keyans_pre_itemsep_skip: \int_compare:nNnT { \l_@@_columns_v_int } > { 1 } { \skip_zero:N \topskip \skip_set_eq:NN \multicolsep \l_@@_minipage_right_skip } } \cs_new_protected:Nn \@@_keyans_minipage_add_space: { \@@_keyans_minipage_set_skip: \@@_unskip_unkern: \mode_if_vertical:TF { \nopagebreak\nointerlineskip } { \par\nopagebreak\nointerlineskip \skip_zero:N \l_@@_partopsep_v_skip } \int_compare:nNnTF { \l_@@_columns_v_int } > { 1 } { \addvspace{ 0.445\box_ht:N \strutbox } } { \addvspace{ 0.250\box_ht:N \strutbox } } } \cs_new_protected:Nn \@@_keyans_pre_itemsep_skip: { \skip_if_eq:nnTF { \l_@@_itemsep_i_skip } { \l_@@_minipage_after_skip } { \skip_set:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_set:Nn \l_@@_multicols_below_v_skip { 0.350\box_ht:N \strutbox } } { \dim_compare:nNnT { \l_@@_itemsep_i_skip } < { \l_@@_minipage_after_skip } { \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_i_skip } \skip_sub:Nn \l_@@_multicols_below_v_skip { \l_@@_itemsep_i_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox } \skip_add:Nn \l_@@_multicols_below_v_skip { 0.350\box_ht:N \strutbox } } \dim_compare:nNnT { \l_@@_itemsep_i_skip } > { \l_@@_minipage_after_skip } { \skip_set:Nn \l_@@_minipage_temp_skip { \l_@@_itemsep_i_skip - \l_@@_minipage_after_skip } \skip_sub:Nn \l_@@_minipage_after_skip { \l_@@_itemsep_i_skip } \skip_sub:Nn \l_@@_multicols_below_v_skip { \l_@@_itemsep_i_skip } \skip_add:Nn \l_@@_minipage_after_skip { 0.150\box_ht:N \strutbox + \l_@@_minipage_temp_skip } \skip_add:Nn \l_@@_multicols_below_v_skip { 0.350\box_ht:N \strutbox + \l_@@_minipage_temp_skip } } } } % \end{macrocode} % \end{macro} % % \subsubsection{Adjustment of vertical spaces for \env{minipage} in \env{enumext*} and \env{keyans*}} % % \begin{macro}{\@@_mini_set_vskip_vii:,\@@_mini_set_vskip_viii:} % The functions \cs{@@_mini_set_vskip_vii:} and \cs{@@_mini_set_vskip_viii:} will take care of determining the % \enquote{adjusted} spaces that we will apply \emph{\enquote{above}} and % \emph{\enquote{below}} the \myvarenv*{__@@_mini_page} environment in % \myenv*{enumext*} and \myenv*{keyans*}. % \iffalse %% Adjustment of vertical spacing for |minipage| in |enumext*| and |keyans*|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_mini_set_vskip_vii: { \skip_zero_new:N \l_@@_minipage_left_skip \skip_gzero_new:N \g_@@_minipage_right_skip \skip_gzero_new:N \g_@@_minipage_after_skip \skip_if_eq:nnTF { \l_@@_topsep_vii_skip } { \c_zero_skip } { \skip_set:Nn \l_@@_minipage_left_skip { 0.5\box_dp:N \strutbox } \skip_gset:Nn \g_@@_minipage_right_skip { 0.325\box_dp:N \strutbox } } { \skip_set:Nn \l_@@_minipage_left_skip { 0.5875\box_dp:N \strutbox } \skip_gset:Nn \g_@@_minipage_right_skip { \l_@@_topsep_vii_skip } \skip_gset:Nn \g_@@_minipage_after_skip { 0.325\box_dp:N \strutbox + \l_@@_topsep_vii_skip } } } \cs_new_protected:Nn \@@_mini_set_vskip_viii: { \skip_zero_new:N \l_@@_minipage_after_skip \skip_zero_new:N \l_@@_minipage_left_skip \skip_zero_new:N \l_@@_minipage_right_skip \skip_if_eq:nnTF { \l_@@_topsep_viii_skip } { \c_zero_skip } { \skip_set:Nn \l_@@_minipage_left_skip { 0.5\box_dp:N \strutbox } \skip_set:Nn \l_@@_minipage_right_skip { \l_@@_partopsep_viii_skip } \skip_set:Nn \l_@@_minipage_after_skip { 1.6\box_dp:N \strutbox } } { \skip_set:Nn \l_@@_minipage_left_skip { 0.5875\box_dp:N \strutbox } \skip_set:Nn \l_@@_minipage_right_skip { \l_@@_topsep_viii_skip } \skip_set:Nn \l_@@_minipage_after_skip { 0.325\box_dp:N \strutbox + \l_@@_topsep_viii_skip } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_mini_addvspace_vii:,\@@_mini_addvspace_viii:} % The functions \cs{@@_mini_addvspace_vii:} and % \cs{@@_mini_addvspace_viii:} will apply the vertical space % \emph{\enquote{only above}} the \myvarenv*{__@@_mini_page} environment on % the \emph{left side} when the \mykey{mini-right} key is active in the % \myenv*{enumext*} and \myenv*{keyans*} environments. % % Here we will NOT take into account whether \hologo{TeX} is in % \mymeta{horizontal mode} or \mymeta{vertical mode}, since |\partopsep| % is equal to \mydim{0pt} in both environments. % \iffalse %% Apply \addvspace above minipage for |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_mini_addvspace_vii: { \@@_mini_set_vskip_vii: \par\nopagebreak \addvspace { \l_@@_minipage_left_skip } } \cs_new_protected:Nn \@@_mini_addvspace_viii: { \@@_mini_set_vskip_viii: \par\nopagebreak \addvspace { \l_@@_minipage_left_skip } } % \end{macrocode} % \end{macro} % % \subsubsection{The command \cs{miniright}}\label{cmd:miniright} % % The command \ics*{miniright} will close the \myvarenv*{__@@_mini_page} % environment on the \emph{\enquote{left side}}, open the \myvarenv*{__@@_mini_page} % environment on the \emph{\enquote{right side}} adding the \emph{adjusted vertical space}. % By default we will add |\centering| when starting the \emph{\enquote{right side}} % environment. The \emph{starred argument} ‘|*|’ inhibits the use of |\centering| % command i.e. the usual \hologo{LaTeX} justification is maintained in % the \myvarenv*{__@@_mini_page} on the \emph{\enquote{right side}}. % % \begin{macro}{\miniright} % First we will perform some checks to prevent the command from being % executed outside the \myenv*{enumext} environment or somewhere % inappropriate then we will call the internal functions to execute it in % the \myenv*{enumext} and \myenv*{keyans} environments. % \iffalse %% Definition of |\miniright| command. % \fi % \begin{macrocode} \NewDocumentCommand \miniright { s } { \int_compare:nNnT { \l_@@_keyans_pic_level_int } = { 1 } { \msg_error:nnn { enumext } { wrong-miniright-place } } % outside \bool_lazy_and:nnT { \int_compare_p:nNn { \l_@@_level_int } = { 0 } } { \int_compare_p:nNn { \l_@@_level_h_int } = { 0 } } { \msg_error:nnn { enumext } { wrong-miniright-place } } % starred env \bool_lazy_and:nnT { \bool_if_p:N \g_@@_starred_bool } { \bool_not_p:n { \l_@@_standar_bool } } { \msg_error:nnn { enumext } { wrong-miniright-starred } } % exec \int_compare:nNnTF { \l_@@_keyans_level_int } = { 1 } { \@@_keyans_mini_right_cmd:n {#1} } { \@@_mini_right_cmd:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_mini_right_cmd:n} % The function \cs{@@_mini_right_cmd:n} takes as argument the \emph{starred} ‘|*|’ % of the \ics*{miniright} command in the \myenv*{enumext} environment. % We check if the \mykey{mini-env} key is active via the variable % \myvarenv{l__@@_minipage_right_X_dim}, if so we close the % \myenv{multicols} environment with the \myvarenv*{__@@_mini_page} % environment on the \emph{\enquote{left side}}, then we open the % \myvarenv*{__@@_mini_page} environment on the \emph{\enquote{right % side}}, apply our adjusted \emph{\enquote{vertical spaces}}, followed by % adding the |\centering| command when the \emph{starred argument} ‘|*|’ is not % present and set zero \myvarenv{g__@@_minipage_stat_int}, otherwise we return an error. % \iffalse %% Internal function for |\miniright| command in enumext. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_mini_right_cmd:n #1 { \dim_compare:nNnTF { \dim_use:c { l_@@_minipage_right_ \@@_level: _dim } } > { \c_zero_dim } { \@@_multicols_stop: \int_compare:nNnT { \int_use:c { l_@@_columns_ \@@_level: _int } } = { 1 } { \par\addvspace{ \l_@@_minipage_after_skip } } \end@@_mini_page \hfill \@@_mini_page{ \dim_use:c { l_@@_minipage_right_ \@@_level: _dim } } \par\nointerlineskip \addvspace { \l_@@_minipage_right_skip } \bool_if:nF {#1} { \centering } \int_gzero:N \g_@@_minipage_stat_int } { \msg_error:nnn { enumext } { wrong-miniright-use } } % paranoia \RenewDocumentCommand \miniright { s } { \msg_error:nn { enumext } { many-miniright-used } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_keyans_mini_right_cmd:n} % The function \cs{@@_keyans_mini_right_cmd:n} takes as argument the \emph{starred} ‘|*|’ % of the \ics*{miniright} command in the \myenv*{keyans} % environment. The implementation of this function is the same as that of % the \cs{@@_mini_right_cmd:n} function of the \myenv*{enumext} % environment. % \iffalse %% Internal function for |\miniright| command in keyans. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_mini_right_cmd:n #1 { \dim_compare:nNnTF { \l_@@_minipage_right_v_dim } > { \c_zero_dim } { \@@_keyans_multicols_stop: \int_compare:nNnT { \l_@@_columns_v_int } = { 1 } { \par\addvspace{ \l_@@_minipage_after_skip } } \end@@_mini_page \hfill \@@_mini_page{ \l_@@_minipage_right_v_dim } \par\nointerlineskip \addvspace { \l_@@_minipage_right_skip } \bool_if:nF {#1} { \centering } \int_gzero:N \g_@@_minipage_stat_int } { \msg_error:nnn { enumext } { wrong-miniright-use } } % paranoia \RenewDocumentCommand \miniright { s } { \msg_error:nn { enumext } { many-miniright-used } } } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{above} and \texttt{below} keys} % % While having controlled the \emph{vertical spaces} within % the \myenv*{enumext} and \myenv*{keyans} environments when using the % \mykey{columns} or \mykey{mini-env} keys, sometimes the % \emph{\enquote{vertical spaces above}} or \emph{\enquote{vertical spaces below}} the environments are % not as expected and it is necessary to be able to apply a % \emph{\enquote{fine correction}} to these. As I have not been able to % correct these \emph{glitches}, the best option is to leave a couple of % \mymeta{keys} dedicated to this purpose, in this case it is best to use % |\vspace| or |\vspace*| when convenient. % % \begin{macro}[int]{above, above*, below, below*} % Define \mykey{above}, \mykey{above*}, \mykey{below} and \mykey{below*} keys for % \myenv*{enumext} and \myenv*{keyans} environments. % \iffalse %% Add |above| and |below| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { above .skip_set:c = { l_@@_vspace_above_#2_skip }, above .value_required:n = true, above* .code:n = \bool_set_true:c { l_@@_vspace_a_star_#2_bool } \keys_set:nn { enumext / #1 } { above = {##1} }, above* .value_required:n = true, below .skip_set:c = { l_@@_vspace_below_#2_skip }, below .value_required:n = true, below* .code:n = \bool_set_true:c { l_@@_vspace_b_star_#2_bool } \keys_set:nn { enumext / #1 } { below = {##1} }, below* .value_required:n = true, } } \clist_map_inline:Nn \c_@@_all_envs_clist { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for \texttt{above} and \texttt{below} keys in \env{enumext}} % % \iffalse %% Function for |above|, |above*|, |below| and |below*| keys in |enumext|. % \fi % \begin{macro}{\@@_vspace_above:,} % The function \cs{@@_vspace_above:} apply the \emph{vertical space above} % the \myenv*{enumext} environment set by the \mykey{above*} and \mykey{above} keys. % \begin{macrocode} \cs_new_protected:Nn \@@_vspace_above: { \skip_if_eq:nnF { \skip_use:c { l_@@_vspace_above_ \@@_level: _skip } } { \c_zero_skip } { \bool_if:cTF { l_@@_vspace_a_star_ \@@_level: _bool } { \vspace*{ \skip_use:c { l_@@_vspace_above_ \@@_level: _skip } } } { \vspace { \skip_use:c { l_@@_vspace_above_ \@@_level: _skip } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_vspace_below:} % The function \cs{@@_vspace_below:} apply the \emph{vertical space below} % the \myenv*{enumext} environment set by the \mykey{below*} and \mykey{below} keys. % \begin{macrocode} \cs_new_protected:Nn \@@_vspace_below: { \skip_if_eq:nnF { \skip_use:c { l_@@_vspace_below_ \@@_level: _skip } } { \c_zero_skip } { \bool_if:cTF { l_@@_vspace_b_star_ \@@_level: _bool } { \vspace*{ \skip_use:c { l_@@_vspace_below_ \@@_level: _skip } } } { \vspace { \skip_use:c { l_@@_vspace_below_ \@@_level: _skip } } } } } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for \texttt{above} and \texttt{below} keys in \env{keyans}} % % \begin{macro}{\@@_vspace_above_v:,} % The function \cs{@@_vspace_above_v:} apply the \emph{vertical space above} % the \myenv*{keyans} environment set by the \mykey{above} and \mykey{above*} keys. % \iffalse %% Function for |above|, |above*|, |below| and |below*| keys in |keyans|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_vspace_above_v: { \skip_if_eq:nnF { \l_@@_vspace_above_v_skip } { \c_zero_skip } { \bool_if:NTF \l_@@_vspace_a_star_v_bool { \vspace*{ \l_@@_vspace_above_v_skip } } { \vspace { \l_@@_vspace_above_v_skip } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_vspace_below_v:} % The function \cs{@@_vspace_below_v:} apply the \emph{vertical space below} % the \myenv*{keyans} environment set by the \mykey{below*} and \mykey{below} keys. % \begin{macrocode} \cs_new_protected:Nn \@@_vspace_below_v: { \skip_if_eq:nnF { \l_@@_vspace_below_v_skip } { \c_zero_skip } { \bool_if:NTF \l_@@_vspace_b_star_v_bool { \vspace*{ \l_@@_vspace_below_v_skip } } { \vspace { \l_@@_vspace_below_v_skip } } } } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for \texttt{above} and \texttt{below} keys in \env{enumext*} \env{keyans*}} % % \begin{macro}{\@@_vspace_above_vii:,\@@_vspace_above_viii:} % The functions \cs{@@_vspace_above_vii:} and \cs{@@_vspace_above_viii:} apply the \emph{vertical space above} % the \myenv*{enumext*} and \myenv*{keyans*} environments set by the \mykey{above} and \mykey{above*} keys. % \iffalse %% Function for |above|, |above*|, |below| and |below*| keys in |enumext*| and |keyans*|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_vspace_above_vii: { \skip_if_eq:nnF { \l_@@_vspace_above_vii_skip } { \c_zero_skip } { \bool_if:NTF \l_@@_vspace_a_star_vii_bool { \vspace*{ \l_@@_vspace_above_vii_skip } } { \vspace { \l_@@_vspace_above_vii_skip } } } } \cs_new_protected:Nn \@@_vspace_above_viii: { \skip_if_eq:nnF { \l_@@_vspace_above_viii_skip } { \c_zero_skip } { \bool_if:NTF \l_@@_vspace_a_star_viii_bool { \vspace*{ \l_@@_vspace_above_viii_skip } } { \vspace { \l_@@_vspace_above_viii_skip } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_vspace_below_vii:, \@@_vspace_below_viii:} % The functions \cs{@@_vspace_below_vii:} and \cs{@@_vspace_below_viii:} % apply the \emph{vertical space below} the \myenv*{enumext*} and % \myenv*{keyans*} environments set by the \mykey{below*} and \mykey{below} keys. % \begin{macrocode} \cs_new_protected:Nn \@@_vspace_below_vii: { \skip_if_eq:nnF { \l_@@_vspace_below_vii_skip } { \c_zero_skip } { \bool_if:NTF \l_@@_vspace_b_star_vii_bool { \vspace*{ \l_@@_vspace_below_vii_skip } } { \vspace { \l_@@_vspace_below_vii_skip } } } } \cs_new_protected:Nn \@@_vspace_below_viii: { \skip_if_eq:nnF { \l_@@_vspace_below_viii_skip } { \c_zero_skip } { \bool_if:NTF \l_@@_vspace_b_star_viii_bool { \vspace*{ \l_@@_vspace_below_viii_skip } } { \vspace { \l_@@_vspace_below_viii_skip } } } } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{series}, \texttt{resume} and \texttt{resume*} keys}\label{key:series} % % The \mykey{series} key is responsible for the whole process of the % \mykey{resume} and \mykey{resume*} keys. The idea behind this is to be % able to absorb the \mymeta{keys} passed to the \emph{optional argument} of the % \emph{\enquote{first level}} of the environments \myenv*{enumext} and \myenv*{enumext*}, but, discarding some specific % \mymeta{keys}. This implementation is adapted directly from the code % provided by Jonathan P. Spratte \texttt(@Skillmon) in \href{https://chat.stackexchange.com/transcript/41?m=65647962#65647962}{chat-TeX-SX} % % \begin{macro}[int]{series, resume, resume*, } % We define the keys \mykey{series}, \mykey{resume} % and \mykey{resume*} only for the \emph{\enquote{first level}} % of \myenv*{enumext} and \myenv*{enumext*}. % \iffalse %% Add |series|, |resume| and |resume*| keys only on first level off |enumext| and |enumext*|. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { series .str_set:N = \l_@@_series_str, series .value_required:n = true, resume .code:n = \@@_resume_series:n {##1}, resume* .code:n = \@@_resume_starred:, resume* .value_forbidden:n = true, } } \clist_map_inline:nn { level-1, enumext* } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \subsubsection{Internal functions for \texttt{series} key} % % \begin{macro}{\@@_filter_series:n, \@@_filter_series_key:n, \@@_filter_series_pair:nn} % The function \cs{@@_filter_series:n} will be in charge of filtering the % \mymeta{keys} we want to store where |{#1}| represents the \emph{optional argument} passed to the environment. % \iffalse %% Internal function for filter keys. % \fi % \begin{macrocode} \cs_new:Npn \@@_filter_series:n #1 { \use:e { \keyval_parse:NNn \@@_filter_series_key:n \@@_filter_series_pair:nn {#1} } } % \end{macrocode} % The function \cs{@@_filter_series_key:n} will be responsible for % filtering the \mymeta{keys} that are passed \emph{\enquote{without value}} by % excluding the \mykey{resume}, \mykey{resume*} and \mykey{base-fix} keys. % \begin{macrocode} \cs_new:Npn \@@_filter_series_key:n #1 { \str_case:nnF {#1} { { resume } {} { resume* } {} { base-fix } {} } { , { \exp_not:n {#1} } } } % \end{macrocode} % The function \cs{@@_filter_series_pair:nn} will be responsible for % filtering the \mymeta{keys} that are passed \emph{\enquote{with value}} by % excluding the \mykey{series}, \mykey{resume}, \mykey{start}, \mykey{start*}, \mykey{save-ans} and % \mykey{save-key} keys. % \begin{macrocode} \cs_new:Npn \@@_filter_series_pair:nn #1#2 { \str_case:nnF {#1} { { series } {} { resume } {} { start } {} { start* } {} { save-ans } {} { save-key } {} } { , { \exp_not:n {#1} } = { \exp_not:n {#2} } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_series:n, \@@_resume_last:n} % The function \cs{@@_parse_series:n} will be responsible for % storing the filtered \mymeta{keys} in the global variable % \myvarenv{g__@@_series_\mymeta[cf=gray]{series name}_tl} along with the % creation of the integer variable % \myvarenv{g__@@_series_\mymeta[cf=gray]{series name}_int} when the key % is passed as an argument; otherwise, it will check the state of the % boolean variable \cs{l_@@_resume_active_bool} set by the keys % \mykey{resume} and \mykey{resume*} and will call the function % \cs{@@_resume_last:n}. % \begin{important}* % The value of boolean variable \cs{l_@@_resume_active_bool} is set to % true by the function \cs{@@_resume_counter:n} which is used by the keys % \mykey{resume} and \mykey{resume*}, in this case we must Make sure it % is set to false so that it does not overwrite the default filtered % \mymeta{keys}. % This function is passed to the function \cs{@@_parse_keys:n} % in the \myenv*{enumext} environment definition (\S\ref{env:enumext}) % and to the function \cs{@@_parse_keys_vii:n} in the \myenv*{enumext*} % environment definition (\S\ref{env:starred}). % \end{important} % \iffalse %% Internal function for parse filter keys used by |series|, |resume| and |resume*| keys. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_parse_series:n #1 { \str_if_empty:NTF \l_@@_series_str { \bool_if:NF \l_@@_resume_active_bool { \@@_resume_last:n {#1} } } { \tl_gclear_new:c { g_@@_series_ \l_@@_series_str _tl } \tl_gset:ce { g_@@_series_ \l_@@_series_str _tl } { \@@_filter_series:n {#1} } \int_if_exist:cF { g_@@_series_ \l_@@_series_str _int } { \int_new:c { g_@@_series_ \l_@@_series_str _int } } } } % \end{macrocode} % The function \cs{@@_resume_last:n} will be in charge % of saving the filtering \mymeta{keys} when the \mykey{series} key is % \emph{not used} and will save them in the variable \myvarenv{g__@@_standar_series_tl} for the % \myenv*{enumext} environment and in the variable \myvarenv{g__@@_starred_series_tl} % for the \myenv*{enumext*} environment. % \iffalse %% Save keys for last environment without |series|, |resume| and |resume*| keys active. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_resume_last:n #1 { \bool_if:NT \l_@@_standar_first_bool { \tl_gclear:N \g_@@_standar_series_tl \tl_gset:Ne \g_@@_standar_series_tl { \@@_filter_series:n {#1} } } \bool_if:NT \l_@@_starred_first_bool { \tl_gclear:N \g_@@_starred_series_tl \tl_gset:Ne \g_@@_starred_series_tl { \@@_filter_series:n {#1} } } } % \end{macrocode} % \end{macro} % % \subsubsection{Internal function to save counter value} % % \begin{macro}{\@@_resume_save_counter:} % % The \cs{@@_resume_save_counter:} function will save the last counter % value to \myvarenv{g__@@_series_\mymeta[cf=gray]{series name}_int} if % the \mykey{series}|=|\mymarg{series name} key has been passed, to % \myvarenv{g__@@_resume_int} if it has passed the key \mykey{resume} % \emph{without value} and the key \mykey{series} is not active, in % \myvarenv{g__@@_series_\mymeta[cf=gray]{series name}_int} if the key % \mykey{resume}|=|\mymarg{series name} has been passed and in % \myvarenv{g__@@_series_\mymeta[cf=gray]{store name}_int} if the key has % been passed \mykey{save-ans}|=|\mymarg{store name}. % % \smallskip % % \begin{important}* % The variables \cs{l_@@_series_str} and \cs{l_@@__resume_name_tl} % contain the same \mymarg{series name} but are executed at different % moments, the integer variable with \cs{l_@@_series_str} sets the value % when execute \mykey{series}|=|\mymarg{series name} and the % integer variable with \cs{l_@@__resume_name_tl} sets the subsequent % values when use \mykey{resume}|=|\mymarg{series name}. % This function is passed to the \myenv*{enumext} environment definition (\S\ref{env:enumext}) % and the \myenv*{enumext*} environment definition (\S\ref{env:starred}). % \end{important} % \iffalse %% Internal function to save counter value and set int vars for |series|, |resume| and |resume*| keys. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_resume_save_counter: { \bool_if:NT \g_@@_standar_bool { \tl_if_empty:NF \l_@@_series_str { \int_gset_eq:cN { g_@@_series_ \l_@@_series_str _int } \value{enumXi} } \tl_if_empty:NTF \l_@@_resume_name_tl { \str_if_empty:NT \l_@@_series_str { \int_gset_eq:NN \g_@@_resume_int \value{enumXi} } } { \int_if_exist:cT { g_@@_series_ \l_@@_resume_name_tl _int } { \int_gset_eq:cN { g_@@_series_ \l_@@_resume_name_tl _int } \value{enumXi} } } \int_if_exist:cT { g_@@_resume_ \l_@@_store_name_tl _int } { \int_gset_eq:cN { g_@@_resume_ \l_@@_store_name_tl _int } \value{enumXi} } } \bool_if:NT \g_@@_starred_bool { \tl_if_empty:NF \l_@@_series_str { \int_gset_eq:cN { g_@@_series_ \l_@@_series_str _int } \value{enumXvii} } \tl_if_empty:NTF \l_@@_resume_name_tl { \str_if_empty:NT \l_@@_series_str { \int_gset_eq:NN \g_@@_resume_vii_int \value{enumXvii} } } { \int_if_exist:cT { g_@@_series_ \l_@@_resume_name_tl _int } { \int_gset_eq:cN { g_@@_series_ \l_@@_resume_name_tl _int } \value{enumXvii} } } \int_if_exist:cT { g_@@_resume_ \l_@@_store_name_tl _int } { \int_gset_eq:cN { g_@@_resume_ \l_@@_store_name_tl _int } \value{enumXvii} } } } % \end{macrocode} % \end{macro} % % \subsubsection{Internal functions for \texttt{resume} key} % % \begin{macro}{\@@_resume_series:n} % The function \cs{@@_resume_series:n} will handle the argument % passed to the \mykey{resume} key in \myenv*{enumext} and \myenv*{enumext*} environments. % If the key is passed \emph{without value} the function % \cs{@@_resume_counter:} is executed which will set the counter % according to the numbering of the last \myenv*{enumext} or \myenv*{enumext*} environments in % which \mykey{series}|=|\mymarg{series name} key is not present, if % the \mykey{save-ans} key is active it will set the counter according to % the value of the integer variable created by that key, otherwise it % will verify that the \myvarenv{g__@@_series_\mymeta[cf=gray]{series name}_tl} % variable set by the \mykey{series} key exists, if so it will pass these % keys to the \emph{first level} of the environment, otherwise it will % return an error. % \iffalse %% Internal function for |resume| key. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_resume_series:n #1 { \tl_if_empty:nTF {#1} { \@@_resume_counter:n { } } { \tl_if_exist:cTF { g_@@_series_ \tl_to_str:n {#1} _tl } { \@@_resume_counter:n {#1} \bool_if:NT \g_@@_standar_bool { \keys_set:nv { enumext / level-1 } { g_@@_series_ \tl_to_str:n {#1} _tl } } \bool_if:NT \g_@@_starred_bool { \keys_set:nv { enumext / enumext* } { g_@@_series_ \tl_to_str:n {#1} _tl } } } { \bool_if:NT \g_@@_standar_bool { \msg_error:nnn { enumext } { unknown-series } {#1} } \bool_if:NT \g_@@_starred_bool { \msg_error:nnn { enumext } { unknown-series } {#1} } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_resume_counter:n, \@@_resume_counter:, \@@_resume_counter_series:, \@@_resume_counter_save_ans:} % The function \cs{@@_resume_counter:n} will set the variable % \cs{l_@@_resume_active_bool} to true and pass the value of the key % \mykey{resume} to the variable \cs{l_@@_series_name_tl} which will % contain the \mymarg{series name}. If the variable \cs{l_@@_series_name_tl} is % empty, that is, we are passing the key \mykey{resume} \emph{without value}, we % will execute the function \cs{@@_resume_counter:} otherwise, when we % pass \mykey{resume}|=|\mymarg{series name} we will execute the function % \cs{@@_resume_counter_series:}, finally we will execute the function % \cs{@@_resume_counter_save_ans:} which is associated with the key % \mykey{save-ans}. % \begin{macrocode} \cs_new_protected:Npn \@@_resume_counter:n #1 { \bool_set_true:N \l_@@_resume_active_bool \tl_set:Nn \l_@@_resume_name_tl {#1} \tl_if_empty:NTF \l_@@_resume_name_tl { \@@_resume_counter: } { \@@_resume_counter_series: } \@@_resume_counter_save_ans: } % \end{macrocode} % The \cs{@@_resume_counter:} function is executed when the % \mykey{resume} key is used \emph{without value}, only the counters for % the \emph{\enquote{first level}} of the environments will be set. % \begin{macrocode} \cs_new_protected:Nn \@@_resume_counter: { \bool_if:NT \g_@@_standar_bool { \int_gincr:N \g_@@_resume_int \int_set_eq:NN \l_@@_start_i_int \g_@@_resume_int } \bool_if:NT \g_@@_starred_bool { \int_gincr:N \g_@@_resume_vii_int \int_set_eq:NN \l_@@_start_vii_int \g_@@_resume_vii_int } } % \end{macrocode} % The function \cs{@@_resume_counter_series:} will be executed when the % \mykey{resume}|=|\mymarg{series name} key is active, setting the % counters for the \emph{\enquote{first level}} of the environments % according to the value of the integer variables created by the % \mykey{series} key. % \begin{macrocode} \cs_new_protected:Nn \@@_resume_counter_series: { \bool_if:NT \g_@@_standar_bool { \int_set:Nn \l_@@_start_i_int { \int_use:c { g_@@_series_ \l_@@_resume_name_tl _int } + 1 } } \bool_if:NT \g_@@_starred_bool { \int_set:Nn \l_@@_start_vii_int { \int_use:c { g_@@_series_ \l_@@_resume_name_tl _int } + 1 } } } % \end{macrocode} % The function \cs{@@_resume_counter_save_ans:} will be executed when the % \mykey{save-ans} key is active along with the \mykey{resume} key, % setting the counters for the \emph{\enquote{first level}} of the % environments according to the value of the integer variables created by % the \mykey{save-ans} key. % \begin{macrocode} \cs_new_protected:Nn \@@_resume_counter_save_ans: { \bool_lazy_and:nnT { \bool_if_p:N \l_@@_standar_first_bool } { \bool_if_p:N \l_@@_store_active_bool } { \int_set:Nn \l_@@_start_i_int { \int_use:c { g_@@_resume_ \l_@@_store_name_tl _int } + 1 } } \bool_lazy_and:nnT { \bool_if_p:N \l_@@_starred_first_bool } { \bool_if_p:N \l_@@_store_active_bool } { \int_set:Nn \l_@@_start_vii_int { \int_use:c { g_@@_resume_ \l_@@_store_name_tl _int } + 1 } } } % \end{macrocode} % \end{macro} % % \subsubsection{Internal function for \texttt{resume*} key} % % \begin{macro}{\@@_resume_starred:} % The function \cs{@@_resume_starred:} will handle the \mykey{resume*} % key in the \myenv*{enumext} and \myenv*{enumext*} environments. This % function will execute the filtered \mymeta{keys} in the last one and will % continue with the numbering according to the last execution of the % environment \myenv*{enumext} or \myenv*{enumext*} in which the keys % \mykey{resume}|=|\mymarg{series name} or \mykey{series}|=|\mymarg{series name} were not active. % \iffalse %% Internal function for |resume*| key. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_resume_starred: { \bool_if:NT \g_@@_standar_bool { \tl_if_empty:NF \g_@@_standar_series_tl { \@@_resume_counter:n { } \keys_set:nV { enumext / level-1 } \g_@@_standar_series_tl } } \bool_if:NT \g_@@_starred_bool { \tl_if_empty:NF \g_@@_starred_series_tl { \@@_resume_counter:n { } \keys_set:nV { enumext / enumext* } \g_@@_starred_series_tl } } } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{save-ans}, \texttt{check-ans} and \texttt{no-store} keys} % % The key \mykey{save-ans} is directly associated with the keys % \mykey{check-ans}, \mykey{no-store}, \mykey{resume} and % \mykey{resume*}, this will activate the entire \emph{\enquote{storage % system}} in the \mypkg*{enumext} package. % % \subsubsection{Setting \texttt{save-ans} key}\label{key:save-ans} % % \begin{macro}[int]{save-ans} % We define the keys \mykey{save-ans} only for the \emph{\enquote{first level}} % of \myenv*{enumext} and \myenv*{enumext*}. % \iffalse %% Add |save-ans| key only on first level off |enumext| and |enumext*|. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { save-ans .code:n = \@@_storing_set:n {##1}, save-ans .value_required:n = true, } } \clist_map_inline:nn { level-1, enumext* } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \subsubsection{Internal functions for \texttt{save-ans} key} % % \begin{macro}{\@@_start_save_ans_msg:, \@@_stop_save_ans_msg:,} % The functions \cs{@@_start_save_ans_msg:} and \cs{@@_stop_save_ans_msg:} % will display in the terminal and |.log| file the environment in which % the \mykey{save-ans} key was executed along with the line at the % beginning and end of it. The function \cs{@@_start_save_ans_msg:} will % be passed to \cs{@@_storing_set:n} and the function % \cs{@@_stop_save_ans_msg:} will be passed to the function % \cs{@@_execute_after_env:}. % \iffalse %% Print/write start and stop environment with |save-ans| key active. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_start_save_ans_msg: { \msg_term:nnVV { enumext } { save-ans-log } \g_@@_envir_name_tl \l_@@_store_name_tl } \cs_new_protected:Nn \@@_stop_save_ans_msg: { \msg_term:nnVV { enumext } { save-ans-log-hook } \g_@@_envir_name_tl \g_@@_store_name_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_storing_set:n, \@@_storing_exec:,} % The function \cs{@@_storing_set:n} first pass the value of the % \mykey{save-ans} key to the variable \cs{l_@@_store_name_tl} % which will contain the \mymarg{store name} of the \emph{sequence} % and \emph{prop list} we will use. If \cs{l_@@_store_name_tl} is % \emph{empty} we return an error message, otherwise will return the % appropriate message \cs{@@_start_save_ans_msg:} and proceed to execute % the function \cs{@@_storing_exec:} for \myenv*{enumext} and % \myenv*{enumext*} environments. % \iffalse %% Function to activate ALL "storing" (and |check-ans|, |no-store|, |resume|, |anskey*|) used by |save-ans| key. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_storing_set:n #1 { \tl_set:Ne \l_@@_store_name_tl {#1} \tl_if_empty:NTF \l_@@_store_name_tl { \bool_lazy_or:nnT { \l_@@_standar_first_bool } { \l_@@_starred_first_bool } { \msg_error:nnV { enumext } { save-ans-empty } \g_@@_envir_name_tl } } { \bool_lazy_or:nnT { \l_@@_standar_first_bool } { \l_@@_starred_first_bool } { \@@_start_save_ans_msg: \@@_storing_exec: } } } % \end{macrocode} % The function \cs{@@_storing_exec:} will set to true the variable % \cs{l_@@_store_active_bool} which activates the use of the % \ics*{anskey} command and the \myenv*{anskey*}, \myenv*{keyans}, % \myenv*{keyans*} and \myenv*{keyanspic} environments and will set % to \enquote{true} the variable \cs{l_@@_check_answers_bool} used for % intenal checking answers mechanism set by the \mykey{check-ans} and \mykey{no-store} % keys, copy \mymarg{store name} into the variable \cs{g_@@_store_name_tl} % and execute the function \cs{@@_anskey_env_make:V} creating the environment % \myenv*{anskey*} (\S\ref{env:anskey}). % \begin{macrocode} \cs_new_protected:Nn \@@_storing_exec: { \bool_set_true:N \l_@@_store_active_bool \bool_set_true:N \l_@@_check_answers_bool \tl_gset:NV \g_@@_store_name_tl \l_@@_store_name_tl \@@_anskey_env_make:V \l_@@_store_name_tl % \end{macrocode} % The \emph{prop list} \myvarenv{g__@@_series_\mymeta[cf=gray]{store % name}_prop} and the \emph{sequence} \myvarenv{g__@@_series_\mymeta[cf=gray]{store name}_seq} % will be created globally to \emph{\enquote{store content}} in case % they do not exist together with the integer variable % \myvarenv{g__@@_series_\mymeta[cf=gray]{store name}_int} used by the keys % \mykey{resume} and \mykey{resume*}. % \begin{macrocode} \prop_if_exist:cF { g_@@_ \l_@@_store_name_tl _prop } { \msg_log:nnV { enumext } { store-prop } \l_@@_store_name_tl \prop_new:c { g_@@_ \l_@@_store_name_tl _prop } } \seq_if_exist:cF { g_@@_ \l_@@_store_name_tl _seq } { \msg_log:nnV { enumext } { store-seq } \l_@@_store_name_tl \seq_new:c { g_@@_ \l_@@_store_name_tl _seq } } \int_if_exist:cF { g_@@_resume_ \l_@@_store_name_tl _int } { \msg_log:nnV { enumext } { store-int } \l_@@_store_name_tl \int_new:c { g_@@_resume_ \l_@@_store_name_tl _int } } } % \end{macrocode} % \end{macro} % % \subsubsection{The check answer mechanism}\label{int:check-answer} % % The internal mechanism for \emph{\enquote{checking answers}} follows this % logic: % % \begin{quote} % If the line begins with |\item| or |\item*| and does NOT % \emph{open a nested environment}, each |\item| or |\item*| must contain a % \emph{single} execution of the |\anskey| command, i.e. the counter of the % executions of the |\anskey| command must be equal to the counter % associated with the sum of executions of |\item| and |\item*|. % % If the line begins with |\item| or |\item*| and \emph{opens a nested % environment} each |\item| or |\item*| in the nested environment must % have a \emph{single} execution of the |\anskey| command and the counter % associated to the sum of |\item| and |\item*| executions must decrementing % by \emph{\enquote{one}} to maintain equality. % % \end{quote} % % In order for the mechanism for the check-answer to work (not counting % \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic}) we need: % % \begin{enumerate}[left=0pt,noitemsep, partopsep=0pt, topsep=5pt] % \item We must keep track of the total number of |\item| and |\item*| (enumerated) that appear within % the environment including the nested levels. % \item We must keep track of the total number of |\item| and |\item*| (enumerated) that appear per % level of nesting. % \item Keeping track of the number of times the environment nests. % \end{enumerate} % % % The integer variable associated to the sum of each |\item| and |\item*| % in the environment \myvarenv{g__@@_item_number_int} must match the % integer variable \myvarenv{g__@@_item_anskey_int} associated % to the execution of the command |\anskey|. We analyze the cases: % % \begin{enumerate}[label=\alph*),left=0pt,noitemsep, partopsep=0pt, topsep=5pt] % \item If the list only has one level the number of |\item + \item*| = \ics*{anskey} % % \item If the list has \emph{nested levels}, for each level of nesting we need to % decrementing by one (for the |\item| or |\item*| that opens the nest) so that the account % remains the same. %^^A \item If there is the option \mykey{no-store} we must add the items within this %^^A level plus one to maintain the equality. % \end{enumerate} % % With \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} it is % enough to increase in one the integer of \ics*{anskey}. The integers % created must be global if they are not lost in the interior levels of % nesting and to execute the test we will use a \emph{\enquote{hook}} % function after closing the \emph{first level} of the environment. % % \subsubsection{Setting \texttt{check-ans} and \texttt{no-store} keys}\label{key:check-ans} % % \begin{macro}[int]{check-ans, no-store} % Now we define the keys \mykey{check-ans} and \mykey{no-store} for all % levels of \myenv*{enumext} and \myenv*{enumext*} environments. % \iffalse %% Add |check-ans| and |no-store| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { check-ans .bool_set:N = \l_@@_check_ans_key_bool, check-ans .initial:n = false, check-ans .value_required:n = true, no-store .code:n = { \bool_set_false:N \l_@@_check_answers_bool \bool_set_false:N \l_@@_check_ans_key_bool }, no-store .value_forbidden:n = true, } } \clist_map_inline:nn { level-1, level-2, level-3, level-4, enumext* } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \subsubsection{Set-up check answer mechanism}\label{int:set-check-answer} % % \begin{macro}{\@@_check_ans_active:, \@@_check_ans_level:,} % The function \cs{@@_check_ans_active:} will first check the state of % the variable \cs{l_@@_store_name_tl}, that is, the \mykey{save-ans} key % is active, if so it will check the state of the variable % \cs{l_@@_check_answers_bool} handled by the key \mykey{no-store} and % will execute the function \cs{@@_check_ans_level:} only if % \emph{\enquote{true}}, i.e. the key \mykey{no-store} is not active. % \iffalse %% Internal function for checking answer mechanism in |enumext| and |enumext*| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_check_ans_active: { \tl_if_empty:NF \l_@@_store_name_tl { \bool_if:NT \l_@@_check_answers_bool { \@@_check_ans_level: } } } % \end{macrocode} % The function \cs{@@_check_ans_level:} will decrement by \emph{\enquote{one}} % the value of the variable \cs{g_@@_item_number_int} which keeps track % of the executions of |\item| and |\item*| for each level of nesting % of the environment \myenv*{enumext}, taking into account whether it % is nested within \myenv*{enumext*} or the opposite and set \cs{l_@@_item_number_bool} % to \emph{\enquote{false}} . % \iffalse %% Decrementing \g_@@_item_number_int for nested level. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_check_ans_level: { \int_case:nn { \l_@@_level_int } { { 1 }{ \bool_lazy_all:nT { { \bool_if_p:N \g_@@_starred_bool } { \int_compare_p:nNn { \l_@@_level_h_int } = { 1 } } } { \int_gdecr:N \g_@@_item_number_int \bool_set_false:N \l_@@_item_number_bool } } { 2 }{ \int_gdecr:N \g_@@_item_number_int \bool_set_false:N \l_@@_item_number_bool } { 3 }{ \int_gdecr:N \g_@@_item_number_int \bool_set_false:N \l_@@_item_number_bool } { 4 }{ \int_gdecr:N \g_@@_item_number_int \bool_set_false:N \l_@@_item_number_bool } } % \end{macrocode} % We should only execute this if \myenv*{enumext*} is nested in the % \emph{\enquote{first level}} of \myenv*{enumext}, for the rest of the % cases the value of \cs{g_@@_item_number_int} is already decreased. % \begin{macrocode} \int_case:nn { \l_@@_level_h_int } { { 1 }{ \bool_lazy_all:nT { { \bool_if_p:N \g_@@_standar_bool } { \int_compare_p:nNn { \l_@@_level_int } = { 1 } } } { \int_gdecr:N \g_@@_item_number_int \bool_set_false:N \l_@@_item_number_bool } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_check_ans_key_hook:} % The function \cs{@@_check_ans_key_hook:} will \emph{export} the status % of the local variable \cs{l_@@_check_ans_key_bool} to the global variable % \cs{g_@@_check_ans_key_bool} only if the key \mykey{check-ans} is active. % \iffalse %% Function to export \l_@@_check_ans_key_bool for |check-ans| key. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_check_ans_key_hook: { \bool_lazy_and:nnT { \bool_if_p:N \l_@@_check_ans_key_bool } { \bool_if_p:N \g_@@_standar_bool } { \bool_gset_true:N \g_@@_check_ans_key_bool } \bool_lazy_and:nnT { \bool_if_p:N \l_@@_check_ans_key_bool } { \bool_if_p:N \g_@@_starred_bool } { \bool_gset_true:N \g_@@_check_ans_key_bool } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_item_answer_diff:} % The function \cs{@@_item_answer_diff:} will set the value of the % variable \cs{g_@@_item_answer_diff_int} which is used by the functions % \cs{@@_check_ans_show:} for the key \mykey{save-ans} and by the % function \cs{@@_check_ans_log:} by the internal \emph{\enquote{check answer}} % mechanism. This function will be passed to the function % \cs{@@_execute_after_env:}. % \iffalse %% Set \g_@@_item_answer_diff_int for |check-ans| key and internal. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_item_answer_diff: { \int_gset:Nn \g_@@_item_answer_diff_int { \int_sign:n { \g_@@_item_number_int - \g_@@_item_anskey_int } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_check_ans_show:, \@@_check_ans_msg_less:, % \@@_check_ans_msg_same_ok:, \@@_check_ans_msg_greater:} % The function \cs{@@_check_ans_show:} will be executed within the % function \cs{@@_execute_after_env:} when the key \mykey{check-ans} is % active, that is, when \cs{g_@@_check_ans_key_bool} is \emph{\enquote{true}} % and will return the appropriate message according to the value of % \cs{g_@@_item_answer_diff_int} set by the function \cs{@@_item_answer_diff:}. % \iffalse %% Function to print |check-ans| key. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_check_ans_show: { \int_case:nn { \g_@@_item_answer_diff_int } { { -1 }{ \@@_check_ans_msg_less: } { 0 }{ \@@_check_ans_msg_same_ok: } { 1 }{ \@@_check_ans_msg_greater: } } } \cs_new_protected:Nn \@@_check_ans_msg_less: { \msg_warning:nneee { enumext } { item-less-answer } { \g_@@_store_name_tl } { \g_@@_envir_name_tl } { \g_@@_start_line_tl } } \cs_new_protected:Nn \@@_check_ans_msg_same_ok: { \msg_term:nneee { enumext } { items-same-answer } { \g_@@_store_name_tl } { \g_@@_envir_name_tl } { \g_@@_start_line_tl } } \cs_new_protected:Nn \@@_check_ans_msg_greater: { \msg_warning:nneee { enumext } { item-greater-answer } { \g_@@_store_name_tl } { \g_@@_envir_name_tl } { \g_@@_start_line_tl } } % \end{macrocode} % \end{macro} % \begin{macro}{\@@_check_ans_log:, \@@_check_ans_log_msg_less:, % \@@_check_ans_log_msg_same_ok:, \@@_check_ans_log_msg_greater:} % The function \cs{@@_check_ans_log:} will be executed within the % function \cs{@@_execute_after_env:} when the key \mykey{check-ans} is % not active, that is, when \cs{g_@@_check_ans_key_bool} is \emph{\enquote{false}} % and write in the log the appropriate message according to the value of % \cs{g_@@_item_answer_diff_int} set by the function % \cs{@@_item_answer_diff:}. % \iffalse %% Function to log check-answer mechanisms. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_check_ans_log: { \int_case:nn { \g_@@_item_answer_diff_int } { { -1 }{ \@@_check_ans_log_msg_less: } { 0 }{ \@@_check_ans_log_msg_same_ok: } { 1 }{ \@@_check_ans_log_msg_greater: } } } \cs_new_protected:Nn \@@_check_ans_log_msg_less: { \msg_log:nneee { enumext } { item-less-answer } { \g_@@_store_name_tl } { \g_@@_envir_name_tl } { \g_@@_start_line_tl } } \cs_new_protected:Nn \@@_check_ans_log_msg_same_ok: { \msg_log:nneee { enumext } { items-same-answer } { \g_@@_store_name_tl } { \g_@@_envir_name_tl } { \g_@@_start_line_tl } } \cs_new_protected:Nn \@@_check_ans_log_msg_greater: { \msg_log:nneee { enumext } { item-greater-answer } { \g_@@_store_name_tl } { \g_@@_envir_name_tl } { \g_@@_start_line_tl } } % \end{macrocode} % \end{macro} % % \subsubsection{Check for \cs{item*} and \cs{anspic*} commands} % % \begin{macro}{\@@_check_starred_cmd:n,} % The function \cs{@@_check_starred_cmd:n} performs an \emph{extra check} % for the \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} environments. % Unlike the \emph{check} executed by \mykey{check-ans} key this one % is not controlled by any key, it is intended to prevent the forgetting % of \ics*{item*} or \ics*{anspic*} in these environments. % \iffalse %% Function for check |\item*| and |\anspic*| commands. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_check_starred_cmd:n #1 { \int_compare:nNnT { \g_@@_check_starred_cmd_int } = { 0 } { \msg_warning:nnnV { enumext } { missing-starred }{ #1 } \l_@@_check_start_line_env_tl } \int_compare:nNnT { \g_@@_check_starred_cmd_int } > { 1 } { \msg_warning:nnnV { enumext } { many-starred }{ #1 } \l_@@_check_start_line_env_tl } \int_gzero:N \g_@@_check_starred_cmd_int \tl_clear:N \l_@@_check_start_line_env_tl } % \end{macrocode} % \end{macro} % % \subsection{Keys and functions associated with storage}\label{int:storage-system} % % \begin{macro}[int]{wrap-ans, wrap-opt, save-sep,mark-ans, mark-pos, show-ans, mark-ref, save-ref} % We add the keys \mykey{wrap-ans}, \mykey{wrap-opt}, \mykey{save-sep}, % \mykey{mark-ans}, \mykey{mark-pos}, \mykey{show-ans}, \mykey{show-pos}, % \mykey{mark-ref} and \mykey{save-ref} related to the \emph{\enquote{storage system}} % and internal mechanism of \emph{\enquote{label and ref}} only at % the \emph{first level} of \myenv*{enumext} and \myenv*{enumext*}. % \iffalse %% Add keys associated with storage on first level of |enumext| and |enumext*|. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { wrap-ans .cs_set_protected:Np = \@@_anskey_wrapper:n ##1, wrap-ans .initial:n = { \fbox{\parbox[t]{\dimeval{\itemwidth -2\fboxsep -2\fboxrule}}{##1}} }, wrap-ans .value_required:n = true, wrap-opt .cs_set_protected:Np = \@@_keyans_wrapper_opt:n ##1, wrap-opt .initial:n = [{##1}], wrap-opt .value_required:n = true, save-sep .tl_set:N = \l_@@_store_keyans_item_opt_sep_tl, save-sep .initial:n = {, ~ }, save-sep .value_required:n = true, mark-ans .tl_set:N = \l_@@_mark_answer_sym_tl, mark-ans .initial:n = \textasteriskcentered, mark-ans .value_required:n = true, mark-pos .choice:, mark-pos / left .code:n = \str_set:Nn \l_@@_mark_position_str { l }, mark-pos / right .code:n = \str_set:Nn \l_@@_mark_position_str { r }, mark-pos / unknown .code:n = \msg_error:nneee { enumext } { unknown-choice } { mark-pos } { left, ~ right } { \exp_not:n {##1} }, mark-pos .initial:n = right, mark-pos .value_required:n = true, show-ans .bool_set:N = \l_@@_show_answer_bool, show-ans .initial:n = false, show-ans .value_required:n = true, show-pos .bool_set:N = \l_@@_show_position_bool, show-pos .initial:n = false, show-pos .value_required:n = true, mark-ref .tl_set:N = \l_@@_mark_ref_sym_tl, mark-ref .initial:n = \textreferencemark, mark-ref .value_required:n = true, save-ref .bool_set:N = \l_@@_store_ref_key_bool, save-ref .initial:n = false, save-ref .value_required:n = true, } } \clist_map_inline:nn { level-1, enumext* } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{mark-pos, show-ans, show-pos} % For the \myenv*{keyans} and \myenv*{keyans*} environments we will % only add the keys \mykey{mark-pos}, \mykey{show-ans} and \mykey{show-pos}. % \iffalse %% Add keys |mark-pos|, |show-pos| and |show-ans| keys for |keyans| and |keyans*| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { mark-pos .choice:, mark-pos / left .code:n = \str_set:Nn \l_@@_mark_position_str { l }, mark-pos / right .code:n = \str_set:Nn \l_@@_mark_position_str { r }, mark-pos .initial:n = right, mark-pos .value_required:n = true, show-ans .bool_set:N = \l_@@_show_answer_bool, show-ans .initial:n = false, show-ans .value_required:n = true, show-pos .bool_set:N = \l_@@_show_position_bool, show-pos .initial:n = false, show-pos .value_required:n = true, } } \clist_map_inline:nn { keyans, keyans* } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \subsubsection{Storing structure of the environments} % % The idea behind \emph{\enquote{storing structure}} in the \emph{sequence} is % to have a copy of the \emph{structure of the environment} in which the key % \mykey{save-ans} is being executed so we must capture the \emph{optional % argument} passed to the levels of the environment in which it is % executed and \emph{\enquote{storing}} this in the \emph{sequence}. % % \begin{macro}{\@@_store_active_keys:n, \@@_store_active_keys_vii:n,} % The functions \cs{@@_store_active_keys:n} and \cs{@@_store_active_keys_vii:n} % will be responsible for the \emph{\enquote{storing keys}} filtered % from the \emph{optional argument} of the environment in which the % key \mykey{save-ans} is executed and the levels within this for the \myenv*{enumext} and % \myenv*{enumext*} environments. We will execute this function only if % the variable \cs{l_@@_store_save_key_X_bool} is false, that is, the key % \mykey{store-key} is not active, establishing the variable % \cs{l_@@_store_save_key_X_tl} with the filtered \mymeta{keys}. % \iffalse %% Internal function for store optional arguments of the environments in seq. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_store_active_keys:n #1 { \bool_if:cF { l_@@_store_save_key_ \@@_level: _bool } { \tl_clear:c { l_@@_save_key_ \@@_level: _tl } \tl_set:ce { l_@@_store_save_key_ \@@_level: _tl } { \@@_filter_save_key:n {#1} } } } \cs_new_protected:Npn \@@_store_active_keys_vii:n #1 { \bool_if:NF \l_@@_store_save_key_vii_bool { \tl_clear:N \l_@@_store_save_key_vii_tl \tl_set:Ne \l_@@_store_save_key_vii_tl { \@@_filter_save_key:n {#1} } } } % \end{macrocode} % \end{macro} % % \subsubsection{Setting \texttt{save-key} key}\label{key:save-key} % % Since this \emph{\enquote{storing structure}} in the \emph{sequence} % established by the \mykey{save-ans} key when executing \ics*{anskey} or \myenv*{anskey*}, % we will not be able to modify it. The best thing here is to have a key % that allows you to modify the \emph{optional argument} of the \emph{\enquote{storing structure}} in % the \emph{sequence}. % % \begin{macro}[int]{save-key} % The values ​​set by this key passed in the \emph{optional argument} of the % \myenv*{enumext} and \myenv*{enumext*} environments will override the % values ​​of the \cs{l_@@_store_save_key_X_tl} variable set by the % functions \cs{@@_store_active_keys:n} and \cs{@@_store_active_keys_vii:n}. % Now define the key \mykey{save-key} for all levels of % \myenv*{enumext} and \myenv*{enumext*} environments. % \iffalse %% Add |save-key| key for |enumext| and |enumext*| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / enumext* } { save-key .code:n = \@@_parse_save_key_vii:n {##1}, save-key .value_required:n = true, } \keys_define:nn { enumext / #1 } { save-key .code:n = \@@_parse_save_key:n {##1}, save-key .value_required:n = true, } } \clist_map_inline:nn { level-1, level-2, level-3, level-4 } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_save_key:n, \@@_parse_save_key_vii:n,} % The functions \cs{@@_parse_save_key:n} and \cs{@@_parse_save_key_vii:n} % will be responsible for \emph{\enquote{storing keys}} in the variable % \myvarenv{l__@@_store_save_key_X_tl} for \myenv*{enumext} and \myenv*{enumext*}. % \iffalse %% Internal function for |save-key| key. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_parse_save_key:n #1 { \bool_set_true:c { l_@@_store_save_key_ \@@_level: _bool } \tl_clear:c { l_@@_save_key_ \@@_level: _tl } \tl_set:ce { l_@@_store_save_key_ \@@_level: _tl } { \@@_filter_save_key:n {#1} } } \cs_new_protected:Npn \@@_parse_save_key_vii:n #1 { \bool_set_true:N \l_@@_store_save_key_vii_bool \tl_clear:N \l_@@_store_save_key_vii_tl \tl_set:Ne \l_@@_store_save_key_vii_tl { \@@_filter_save_key:n {#1} } } % \end{macrocode} % \end{macro} % % \subsubsection{Internal functions to store optional arguments} % % \begin{macro}{\@@_filter_save_key:n, \@@_filter_save_key_key:n, \@@_filter_save_key_pair:nn} % The function \cs{@@_filter_save_key:n} will be in charge of % \emph{\enquote{filtering keys}} we want to \emph{stored} in % \emph{sequence} where |{#1}| represents the \emph{optional argument} % passed to the environment. % \iffalse %% Internal function for "filter keys" for |save-key| key. % \fi % \begin{macrocode} \cs_new:Npn \@@_filter_save_key:n #1 { \use:e { \keyval_parse:NNn \@@_filter_save_key_key:n \@@_filter_save_key_pair:nn {#1} } } % \end{macrocode} % The function \cs{@@_filter_save_key_key:n} will be responsible for % \emph{\enquote{filtering keys}} that are passed \emph{\enquote{without value}} by % excluding the \mykey{resume}, \mykey{resume*}, \mykey{no-store} and \mykey{base-fix} keys. % \begin{macrocode} \cs_new:Npn \@@_filter_save_key_key:n #1 { \str_case:nnF {#1} { { resume } {} { resume* } {} { no-store } {} { base-fix } {} } { , { \exp_not:n {#1} } } } % \end{macrocode} % The function \cs{@@_filter_save_key_pair:nn} will be responsible for % \emph{\enquote{filtering keys}} that are passed \emph{\enquote{with value}} by % excluding the \mykey{series}, \mykey{resume}, \mykey{save-ans}, \mykey{save-ref}, \mykey{check-ans}, % \mykey{show-ans}, \mykey{save-pos}, \mykey{wrap-ans}, \mykey{mark-ans}, % \mykey{wrap-opt}, \mykey{save-sep}, \mykey{mark-ref}, \mykey{mini-env}, \mykey{mini-sep}, % \mykey{mini-right} and \mykey{mini-right*} keys. % \begin{macrocode} \cs_new:Npn \@@_filter_save_key_pair:nn #1#2 { \str_case:nnF {#1} { { series } {} { resume } {} { save-ans } {} { save-ref } {} { save-key } {} { check-ans } {} { show-ans } {} { show-pos } {} { wrap-ans } {} { mark-ans } {} { wrap-opt } {} { save-sep } {} { mark-ref } {} { mini-env } {} { mini-sep } {} { mini-right } {} { mini-right* } {} } { , { \exp_not:n {#1} } = { \exp_not:n {#2} } } } % \end{macrocode} % \end{macro} % % \subsubsection{Function for storing content in prop list} % % \begin{macro}{\@@_store_addto_prop:n, \@@_store_addto_prop:V} % The function \cs{@@_store_addto_prop:n} stores the \mymarg{content} in % \emph{prop list} defined by \mykey{save-ans} key. The \emph{\enquote{stored % content}} is retrieved by means of the \ics*{getkeyans} command. % % \smallskip % % The form in which the \mymarg{content} is \emph{\enquote{stored}} in the % \emph{prop list} is \mymarg{position}\mymarg{content}. This % function is used by \ics*{anskey} in \myenv*{enumext} and \myenv*{enumext*} % environments, \ics*{item*} in \myenv*{keyans} and \myenv*{keyans*} % environments and \ics*{anspic*} in \myenv*{keyanspic} environment. % \iffalse %% Function for store content to prop list. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_store_addto_prop:n #1 { \prop_gput_if_not_in:cen { g_@@_ \l_@@_store_name_tl _prop } { \int_eval:n { \prop_count:c { g_@@_ \l_@@_store_name_tl _prop } + 1 } } { #1 } } \cs_generate_variant:Nn \@@_store_addto_prop:n { V } % \end{macrocode} % \end{macro} % % \subsubsection{Function for storing content in sequence} % % \begin{macro}{\@@_store_addto_seq:n, \@@_store_addto_seq:v, \@@_store_addto_seq:V} % The function \cs{@@_store_addto_seq:n} stores the \mymarg{content} in % \emph{sequence} defined by \mykey{save-ans} key. This function % is used by \ics*{anskey} in \myenv*{enumext}, \ics*{item*} in % \myenv*{keyans} and \ics*{anspic} in \myenv*{keyanspic}. % % \smallskip % % The form in which the \mymarg{content} is stored in \emph{sequence} is in % a internal \myenv*{enumext} or \myenv*{enumext*} environments with % the \emph{\enquote{same structure}} in which the command was executed. % % The \emph{\enquote{stored content}} is retrieved by means of the % \ics*{printkeyans} command. % \iffalse %% Function for store content to sequence. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_store_addto_seq:n #1 { \seq_gput_right:cn { g_@@_ \l_@@_store_name_tl _seq } { #1 } } \cs_generate_variant:Nn \@@_store_addto_seq:n { v, V } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for storing structure in the sequence} % % \begin{macro}{\@@_store_level_open:, \@@_store_level_close:,} % The \emph{\enquote{storing structure}} is handled by the functions % \cs{@@_store_level_open:} and \cs{@@_store_level_close:} which are % executed per level within the \myenv*{enumext} environment. % \iffalse %% Function for storing structure level execution of |\anskey| on |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_store_level_open: { \bool_if:NT \l_@@_check_answers_bool { \tl_if_empty:cTF { l_@@_store_save_key_ \@@_level: _tl } { \@@_store_addto_seq:n { \item \begin{enumext} } } { \tl_put_left:cn { l_@@_store_save_key_ \@@_level: _tl } { \item \begin{enumext} [ } \tl_put_right:cn { l_@@_store_save_key_ \@@_level: _tl } { ] } \@@_store_addto_seq:v { l_@@_store_save_key_ \@@_level: _tl } } } } \cs_new_protected:Nn \@@_store_level_close: { \bool_if:NT \l_@@_check_answers_bool { \@@_store_addto_seq:n { \end{enumext} } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_store_level_open_vii:, \@@_store_level_close_vii:,} % The \emph{\enquote{storing structure}} is handled by the functions % \cs{@@_store_level_open_vii:} and \cs{@@_store_level_close_vii:} % which are executed in the \myenv*{enumext*} environment. % % \iffalse %% Function storing structure level execution of |\anskey| and |anskey*| on |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_store_level_open_vii: { \bool_if:NT \l_@@_check_answers_bool { \tl_if_empty:NTF \l_@@_store_save_key_vii_tl { \@@_store_addto_seq:n { \item \begin{enumext*} } } { \tl_put_left:Nn \l_@@_store_save_key_vii_tl { \item \begin{enumext*}[ } \tl_put_right:Nn \l_@@_store_save_key_vii_tl { ] } \@@_store_addto_seq:V \l_@@_store_save_key_vii_tl } } } \cs_new_protected:Nn \@@_store_level_close_vii: { \bool_if:NT \l_@@_check_answers_bool { \@@_store_addto_seq:n { \end{enumext*} } } } % \end{macrocode} % \end{macro} % % \subsubsection{Function for show marks and position} % % \begin{macro}{\@@_print_keyans_box:NN, \@@_print_keyans_box:cc } % The function \cs{@@_print_keyans_box:NN} print a box in the left % margin with \cs{l_@@_mark_answer_sym_tl} used by the \mykey{wrap-ans}, % \mykey{show-ans} and \mykey{show-pos} keys. The function takes two % arguments: % % \smallskip % % \begin{arguments} % \item \myvarenv{l__@@_labelwidth_X_dim} % \item \myvarenv{l__@@_labelsep_X_dim} % \end{arguments} % % \iffalse %% Function for put content in box on left margin. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_print_keyans_box:NN { \mode_leave_vertical: \skip_horizontal:n { -\dim_use:N #2 } \makebox[0pt][ r ] { \makebox[ \dim_use:N #1 ][ \l_@@_mark_position_str ] { \tl_use:N \l_@@_mark_answer_sym_tl } } \skip_horizontal:n { \dim_use:N #2 } } \cs_generate_variant:Nn \@@_print_keyans_box:NN { cc } % \end{macrocode} % \end{macro} % % \subsection{The internal label and ref}\label{fun:internal-label-ref} % % The function \cs{@@_store_internal_ref:} handles the % \emph{\enquote{internal label and ref}} system used by the \mykey{save-ref} % and \mykey{mark-ref} keys for \ics*{anskey} will allow to execute % \ics{ref}\mymarg{store name \textnormal{\textcolor{red}{:}} position} and % will return |1||.(a)||.i||.A|. % % \begin{macro}{\@@_store_internal_ref:} % First we will remove the dots \enquote{\textcolor{red}{.}} from % the current \mymeta{labels}, we do not want to get double dots in % our references, then we will place this in the variable % \cs{l_@@_newlabel_arg_two_tl}. % \iffalse %% Internal label and ref function for |\anskey| and |anskey*|. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_store_internal_ref: { \cs_set_protected:Npn \@@_tmp:n ##1 { \tl_set_eq:cc { l_@@_label_copy_##1_tl } { l_@@_label_##1_tl } \tl_reverse:c { l_@@_label_copy_##1_tl } \tl_remove_once:cn { l_@@_label_copy_##1_tl } { . } \tl_reverse:c { l_@@_label_copy_##1_tl } } \clist_map_inline:nn { i, ii, iii, iv, vii } { \@@_tmp:n {##1} } \cs_set:Npn \@@_tmp:n ##1 { . \tl_use:c { l_@@_label_copy_ \int_to_roman:n {##1} _tl } } % \end{macrocode} % Here we need to analyse the cases where the environment is started with % \myenv*{enumext*} and if \ics*{anskey} or \myenv*{anskey*} is running % alone in it or if it is running in a nested \myenv*{enumext} environment % within the starting environment. % \begin{macrocode} \bool_lazy_all:nT { { \bool_if_p:N \g_@@_starred_bool } { \int_compare_p:nNn { \l_@@_level_int } = { 0 } } } { \tl_put_right:Ne \l_@@_newlabel_arg_two_tl { \tl_use:N \l_@@_label_copy_vii_tl } } \bool_lazy_all:nT { { \bool_not_p:n { \g_@@_standar_bool } } { \bool_if_p:N \l_@@_standar_bool } { \int_compare_p:nNn { \l_@@_level_int } > { 0 } } } { \tl_put_right:Ne \l_@@_newlabel_arg_two_tl { \tl_use:N \l_@@_label_copy_vii_tl \int_step_function:nnN { 1 } { \l_@@_level_int } \@@_tmp:n } } % \end{macrocode} % If started with \myenv*{enumext} and if \ics*{anskey} or \myenv*{anskey*} % is running alone in it or if it is running in a nested \myenv*{enumext*} % environment within the starting environment. % \begin{macrocode} \bool_lazy_all:nT { { \bool_if_p:N \g_@@_standar_bool } { \int_compare_p:nNn { \l_@@_level_int } > { 0 } } { \int_compare_p:nNn { \l_@@_level_h_int } = { 0 } } } { \tl_put_right:Ne \l_@@_newlabel_arg_two_tl { \tl_use:N \l_@@_label_copy_i_tl \int_step_function:nnN { 2 } { \l_@@_level_int } \@@_tmp:n } } \cs_set:Npn \@@_tmp:n ##1 { \tl_use:c { l_@@_label_copy_ \int_to_roman:n {##1} _tl } . } \bool_lazy_all:nT { { \bool_if_p:N \g_@@_standar_bool } { \bool_if_p:N \l_@@_starred_bool } { \int_compare_p:nNn { \l_@@_level_int } > { 0 } } } { \tl_put_right:Ne \l_@@_newlabel_arg_two_tl { \int_step_function:nnN { 1 } { \l_@@_level_int } \@@_tmp:n \tl_use:N \l_@@_label_copy_vii_tl } } % \end{macrocode} % Now we set the variable \cs{l_@@_newlabel_arg_one_tl} which will % contain \mymarg{store name \textnormal{\textcolor{red}{:}} position}. % \begin{macrocode} \tl_put_right:Ne \l_@@_newlabel_arg_one_tl { \l_@@_store_name_tl \c_colon_str \int_eval:n { \prop_count:c { g_@@_ \l_@@_store_name_tl _prop } } } % \end{macrocode} % Now execute the function \cs{@@_newlabel:nn} and save the result in % the variable \cs{l_@@_write_aux_file_tl} and finally we write in the % |.aux| file. % \begin{macrocode} \tl_put_right:Ne \l_@@_write_aux_file_tl { \@@_newlabel:nn { \exp_not:V \l_@@_newlabel_arg_one_tl } { \l_@@_newlabel_arg_two_tl } } \l_@@_write_aux_file_tl } % \end{macrocode} % \end{macro} % % \subsection{Common functions for \cs{anskey} and \texttt{anskey*} environment} % % \begin{macro}{\@@_store_anskey_code:n} % The internal function \cs{@@_store_anskey_code:n} first we pass the % \mymarg{argument} to the \emph{prop list}, then checks the % state of the variable \cs{l_@@_store_ref_key_bool} handled by the % \mykey{save-ref} key and will call the function \cs{@@_store_internal_ref:} % for the \emph{\enquote{internal label and ref}} system. Followed by % this if the \mykey{show-ans} or \mykey{show-pos} keys are active we % will show the \emph{\enquote{wrapped}} \mymarg{argument}. % \iffalse %% Internal function of |\anskey| for store content. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_store_anskey_code:n #1 { \int_gincr:N \g_@@_item_anskey_int \@@_store_addto_prop:n {#1} \bool_if:NT \l_@@_store_ref_key_bool { \@@_store_internal_ref: } \@@_anskey_show_wrap_left:n { #1 } % \end{macrocode} % Now we start processing the \myoarg{key \textnormal{\textcolor{gray}{=}} val} % passed to the command to build our |\item| in the variable \cs{l_@@_store_anskey_arg_tl} % which we will \emph{\enquote{store}} in the \emph{sequence}. % First we clear the variable \cs{l_@@_store_anskey_arg_tl} and process % the \mymeta{keys}, if the \mykeycmd{break-col} key is present and % the command is running under \myenv*{enumext} (not in \myenv*{enumext*}) % we will add \ics{columnbreak} and then |\item|. % \begin{macrocode} \tl_clear:N \l_@@_store_anskey_arg_tl \bool_lazy_and:nnT { \bool_if_p:N \l_@@_store_columns_break_bool } { \bool_not_p:n { \l_@@_starred_bool } } { \tl_put_left:Nn \l_@@_store_anskey_arg_tl { \columnbreak } } \tl_put_right:Nn \l_@@_store_anskey_arg_tl { \item } % \end{macrocode} % If the \mykeycmd{item-join} key is present and the command is running under % \myenv*{enumext*} we will add \myparg{number} to \cs{l_@@_store_anskey_arg_tl}. % \begin{macrocode} \bool_lazy_and:nnT { \bool_not_p:n { \l_@@_starred_bool } } { \int_compare_p:nNn { \l_@@_store_item_join_int } > { 1 } } { \tl_put_right:Ne \l_@@_store_anskey_arg_tl { ( \exp_not:V \l_@@_store_item_join_int ) } } % \end{macrocode} % And now we will review the keys \mykeycmd{item-star}, \mykeycmd{item-sym*} and % \mykeycmd{item-pos*} and pass them to \cs{l_@@_store_anskey_arg_tl} % along with the \mymarg{argument} for |\anskey| or \mymeta{body} for |anskey*|. % \begin{macrocode} \bool_if:NTF \l_@@_store_item_star_bool { \tl_put_right:Nn \l_@@_store_anskey_arg_tl { * } \tl_if_empty:NF \l_@@_store_item_symbol_tl { \tl_put_right:Ne \l_@@_store_anskey_arg_tl { [ \exp_not:V \l_@@_store_item_symbol_tl ] } } \dim_compare:nT { \l_@@_store_item_symbol_sep_dim != \c_zero_dim } { \tl_put_right:Ne \l_@@_store_anskey_arg_tl { [ \exp_not:V \l_@@_store_item_symbol_sep_dim ] } } \tl_put_right:Nn \l_@@_store_anskey_arg_tl {#1} } { \tl_put_right:Nn \l_@@_store_anskey_arg_tl {#1} } % \end{macrocode} % Finally we check if the \mykey{save-ref} key are active along with the % \mypkg{hyperref} package load, if both conditions are met, it will % create the \ics{hyperlink} with \emph{\enquote{symbol}} set by \mykey{mark-ref} % key and then store in \emph{sequence}. % \begin{macrocode} \bool_lazy_and:nnT { \bool_if_p:N \l_@@_store_ref_key_bool } { \bool_if_p:N \l_@@_hyperref_bool } { \tl_put_right:Ne \l_@@_store_anskey_arg_tl { \hfill \exp_not:N \hyperlink { \exp_not:V \l_@@_newlabel_arg_one_tl } { \exp_not:V \l_@@_mark_ref_sym_tl } } } \@@_store_addto_seq:V \l_@@_store_anskey_arg_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_anskey_show_wrap_arg:n,} % The function \cs{@@_anskey_show_wrap_arg:n} \emph{\enquote{wraps}} % the \mymarg{argument} passed to \ics*{anskey} and the \mymeta{body} % for \myenv*{anskey*} when using the \mykey{wrap-ans} key. % \iffalse %% Internal |wrap-ans| implementation for |\anskey| and |anskey*|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_anskey_show_wrap_arg:n #1 { \par \bool_if:NTF \l_@@_starred_bool { \@@_print_keyans_box:NN \l_@@_labelwidth_vii_dim \l_@@_labelsep_vii_dim } { \@@_print_keyans_box:cc { l_@@_labelwidth_ \@@_level: _dim } { l_@@_labelsep_ \@@_level: _dim } } \@@_anskey_wrapper:n { #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}{ \@@_anskey_show_wrap_left:n } % The function \cs{@@_anskey_show_wrap_left:n} will show the % \emph{\enquote{mark}} defined by the \mykey{mark-ans} key or the % \emph{\enquote{position}} of the \mymarg{content} stored in the \emph{prop list} % when using the \mykey{show-pos} key on the left margin next to the % \emph{\enquote{wraps}} \mymarg{argument} passed to \ics*{anskey} and % the \mymeta{body} in \myenv*{anskey*} on the right side when using % the \mykey{show-ans} key. % \iffalse %% Internal |show-ans| and |show-pos| implementation for |\anskey| and |anskey*|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_anskey_show_wrap_left:n #1 { \bool_if:NT \l_@@_show_answer_bool { \@@_anskey_show_wrap_arg:n { #1 } } \bool_if:NT \l_@@_show_position_bool { \tl_set:Ne \l_@@_mark_answer_sym_tl { \group_begin: \exp_not:N \normalfont \exp_not:N \footnotesize [ \int_eval:n { \prop_count:c { g_@@_ \l_@@_store_name_tl _prop } } ] \group_end: } \@@_anskey_show_wrap_arg:n { #1 } } } % \end{macrocode} % \end{macro} % % \subsection{The command \cs{anskey}}\label{cmd:anskey} % % Since we will be \emph{\enquote{storing content}} in a \myenv{list} environment % within \emph{sequences} and can (more or less) manage the options % passed to each level, it is necessary that we have a little more % control over |\item| when storing. % % \smallskip % % The \ics*{anskey} command will cover this point and give it similar % behaviour to that of |\item| in the \myenv*{enumext} and \myenv*{enumext*} % environments executed as follows \ics*{anskey}\myoarg{key \textnormal{\textcolor{gray}{=}} val}\mymarg{content}. % % \begin{macro}{\@@_anskey_unknown:n, \@@_anskey_unknown:nn} % First we'll add the keys \mykeycmd{break-col}, \mykeycmd{item-join}, % \mykeycmd{item-star}, \mykeycmd{item-sym*} and \mykeycmd{item-pos*}. % \iffalse %% Add |key=val| for |\anskey|. % \fi % \begin{macrocode} \keys_define:nn { enumext / anskey } { break-col .bool_set:N = \l_@@_store_columns_break_bool, break-col .default:n = true, break-col .value_forbidden:n = true, item-join .int_set:N = \l_@@_store_item_join_int, item-join .value_required:n = true, item-star .bool_set:N = \l_@@_store_item_star_bool, item-star .default:n = true, item-star .value_forbidden:n = true, item-sym* .tl_set:N = \l_@@_store_item_symbol_tl, item-sym* .value_required:n = true, item-pos* .dim_set:N = \l_@@_store_item_symbol_sep_dim, item-pos* .value_required:n = true, unknown .code:n = { \@@_anskey_unknown:n {#1} }, } % \end{macrocode} % The \mymeta{keys} are stored in \cs{l_keys_key_str} and the value % (if any) is passed as an argument to the function \cs{@@_anskey_unknown:n}. % \begin{macrocode} \cs_new_protected:Npn \@@_anskey_unknown:n #1 { \exp_args:NV \@@_anskey_unknown:nn \l_keys_key_str {#1} } \cs_new_protected:Npn \@@_anskey_unknown:nn #1 #2 { \tl_if_blank:nTF {#2} { \msg_error:nnn { enumext } { anskey-cmd-key-unknown } {#1} } { \msg_error:nnnn { enumext } { anskey-cmd-key-value-unknown } {#1} {#2} } } % \end{macrocode} % \end{macro} % % \begin{important}* % The \ics*{anskey} command will only be present when using the % \mykey{save-ans} key in \myenv*{enumext} and \myenv*{enumext*} % environments, otherwise it will return an error. % \end{important} % % \begin{macro}{\anskey} % We will first call the function \cs{@@_anskey_safe_outer:} to be % sure where we execute the command, then we will check the state of the % variable \cs{l_@@_check_answers_bool} set by the key \mykey{no-store}, % if is true we will increment \cs{g_@@_item_anskey_int} for the internal % \emph{\enquote{check answer}} system and execute the function % \cs{@@_anskey_safe_inner:n} to ensure that the command is not % nested and that the argument is not empty, finally search the % \myoarg{key \textnormal{\textcolor{gray}{=}} val} and call the % function \cs{@@_store_anskey_code:n}. % \iffalse %% Define the user command |\anskey|. % \fi % \begin{macrocode} \NewDocumentCommand \anskey { o +m } { \@@_anskey_safe_outer: \group_begin: \bool_if:NT \l_@@_check_answers_bool { \tl_if_novalue:nF {#1} { \keys_set:nn { enumext / anskey } {#1} } \tl_if_blank:nTF {#2} { \msg_error:nn { enumext } { anskey-empty-arg } } { \@@_anskey_safe_inner: \@@_store_anskey_code:n {#2} } } \group_end: } % \end{macrocode} % \end{macro} % % \subsubsection{Internal functions for the command} % % \begin{macro}{\@@_anskey_safe_outer:, \@@_anskey_safe_inner:} % The \cs{@@_store_anskey_safe_outer:} function will return the % appropriate messages when the command is executed outside the % environment in which the \mykey{save-ans} key was activated. % \iffalse %% Internal function for msg when |\anskey| is outer. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_safe_outer: { \bool_if:NF \l_@@_store_active_bool { \msg_error:nnnn { enumext } { anskey-wrong-place }{ anskey }{ enumext } } \int_compare:nNnT { \l_@@_keyans_level_int } = { 1 } { \msg_error:nnnn { enumext } { command-wrong-place }{ anskey }{ keyans } } \int_compare:nNnT { \l_@@_keyans_level_h_int } = { 1 } { \msg_error:nnnn { enumext } { command-wrong-place }{ anskey }{ keyans* } } \int_compare:nNnT { \l_@@_keyans_pic_level_int } = { 1 } { \msg_error:nnnn { enumext } { command-wrong-place }{ anskey }{ keyanspic } } } % \end{macrocode} % The \cs{@@_anskey_safe_inner:} function will first check if the % command is nested, if preceded by a not numbered |\item| or if it is % in \emph{math mode} returning the appropriate messages. % \iffalse %% Internal function for msg when |\anskey| is inner, math-mode or arg is empty. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_safe_inner: { \int_incr:N \l_@@_anskey_level_int \int_compare:nNnT { \l_@@_anskey_level_int } > { 1 } { \msg_error:nn { enumext } { anskey-nested } } \bool_if:NF \l_@@_item_number_bool { \msg_error:nn { enumext } { anskey-unnumber-item } } \mode_if_math:T { \msg_error:nne { enumext } { anskey-math-mode } { \c_backslash_str anskey } } } % \end{macrocode} % \end{macro} % % \subsection{The environment \env{anskey*}}\label{env:anskey} % % Managing \emph{verbatim content} in an environment is quite complicated, I % learned that when creating the \mypkg{scontents} package, so to be able % to have support at this point it is best to play a little with the % internal code of \mypkg{scontents} and \emph{hooks}. % Some considerations I should have here before implementing this: % % \begin{itemize}[left=10pt,nosep, topsep=2pt] % \item If some package, class or user has defined the environment with the % same name somewhere in the document it would be a problem, you would % not know what argument has been passed to |store-env|, if you are using % the key |print-env| or the |write-out| key, sure, I can detect and % modify it within the \myenv*{enumext} and \myenv*{enumext*} % environments, but it would look strange not to have some keys available % when running within these environments. % % \item A better (perhaps a bit paranoid) option is to define it within the % environment in which the |save-ans| key is executed. and have it % available only when that key is executed, here I would have absolute % control of the \mymeta{keys} and I make sure that |write-out| is not used, then % using \emph{hooks after} I undefine it and using \emph{hook before} I check if it has % been created by any package, class or user and I return a error, % then the user will have to see how to solve the problem. % \end{itemize} % % \begin{macro}[int]{\@@_undefine_anskey_env:,} % The function \cs{@@_undefine_anskey_env:} will undefine the environment % \myenv*{anskey*} and will be passed to the function % \cs{@@_execute_after_env:} (\S\ref{fun:exec-after-env}) which is % executed after the environment in which the key \mykey{save-ans} is active. % \begin{macrocode} \cs_new_protected:Nn \@@_undefine_anskey_env: { \cs_undefine:c { anskey* } \cs_undefine:c { endanskey* } \cs_undefine:c { __scontents_anskey*_env_begin: } \cs_undefine:c { __scontents_anskey*_env_end: } } % \end{macrocode} % Detection of the \myenv*{anskey*} environment outside the % \myenv*{enumext} and \myenv*{enumext*} environments. % \iffalse %% Hooks for |anskey*| environment out off |enumext| and |enumext*| environments. % \fi % \begin{macrocode} \@@_before_env:nn { enumext } { \bool_lazy_and:nnT { \int_compare_p:nNn { \l_@@_level_int } = { 0 } } { \int_compare_p:nNn { \l_@@_level_h_int } = { 0 } } { \cs_if_free:cF { __scontents_anskey*_env_begin: } { \msg_error:nnn { enumext } { anskey-env-error } { anskey* } } } } \@@_before_env:nn { enumext* } { \bool_lazy_and:nnT { \int_compare_p:nNn { \l_@@_level_int } = { 0 } } { \int_compare_p:nNn { \l_@@_level_h_int } = { 0 } } { \cs_if_free:cF { __scontents_anskey*_env_begin: } { \msg_error:nnn { enumext } { anskey-env-error } { anskey* } } } } % \end{macrocode} % Detection of the \myenv*{anskey*} environment inside the \myenv*{keyans}, % \myenv*{keyans*} and \myenv*{keyanspic} environments, if preceded by % a not numbered |\item| or if it is in \emph{math mode} returning % the appropriate messages. % \iffalse %% Hooks for |anskey*| inside the |keyans|, |keyans*| and |keyanspic| environments, math-mode ans not number |\item|. % \fi % \begin{macrocode} \@@_before_env:nn { anskey* } { \int_compare:nNnT { \l_@@_keyans_level_int } = { 1 } { \msg_error:nnn { enumext } { anskey-env-wrong }{ keyans } } \int_compare:nNnT { \l_@@_keyans_level_h_int } = { 1 } { \msg_error:nnn { enumext } { anskey-env-wrong } { keyans* } } \int_compare:nNnT { \l_@@_keyans_pic_level_int } = { 1 } { \msg_error:nnn { enumext } { anskey-env-wrong } { keyanspic } } \bool_if:NF \l_@@_item_number_bool { \msg_error:nn { enumext } { anskey-unnumber-item } } \mode_if_math:T { \msg_error:nnn { enumext } { anskey-math-mode } { anskey* } } } % \end{macrocode} % \end{macro} % % \begin{macro}{anskey*, \@@_anskey_env_make:n, \@@_anskey_env_make:V, % \@@_anskey_env_define_keys:, \@@_anskey_env_unknown:n, % \@@_anskey_env_unknown:nn, \@@_anskey_env_reset_keys:, % \@@_rescan_anskey_env:n,} % The function \cs{@@_anskey_env_make:n} creates the environment % \myenv*{anskey*} (\emph{custom version} of \myenv{scontents} % environment) by setting the initial keys |store-env=|\mymarg{store name} % and |print-env=false|. % % To maintain the \emph{scope} of the environment and that it is only active % when the key \mykey{save-ans} is active we will pass this function to % the function \cs{@@_storing_exec:} (\S\ref{key:save-ans}) and we % will execute it only if the variable \cs{l_@@_anskey_env_bool} is true, % with this we prevent it from being executed again when the environment % is nested and the key \mykey{save-ans} is active, which returns an % error for part of the package \mypkg{scontents}. % \iffalse %% Function for define |anskey*| environment using scontents. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_anskey_env_make:n #1 { \bool_if:NT \l_@@_anskey_env_bool { \newenvsc{anskey*}[store-env=#1,print-env=false] \@@_anskey_env_exec: } } \cs_generate_variant:Nn \@@_anskey_env_make:n { V } % \end{macrocode} % The function \cs{@@_anskey_env_define_keys:} will add the keys % \mykeycmd{break-col}, \mykeycmd{item-join}, \mykeycmd{item-join}, % \mykeycmd{item-star}, \mykeycmd{item-sym*} and \mykeycmd{item-pos*} % and will leave the keys |print-env|, |store-env| and |write-out| % undefined. We will apply this function using the \emph{hook} function % \cs{@@_before_env:nn}. % \iffalse %% Define keys for |anskey*| environment using scontents PATH. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_env_define_keys: { \keys_define:nn { scontents / scontents } { break-col .bool_gset:N = \g_@@_store_columns_break_bool, break-col .default:n = true, break-col .value_forbidden:n = true, item-join .int_gset:N = \g_@@_store_item_join_int, item-join .value_required:n = true, item-star .bool_gset:N = \g_@@_store_item_star_bool, item-star .default:n = true, item-star .value_forbidden:n = true, item-sym* .tl_gset:N = \g_@@_store_item_symbol_tl, item-sym* .value_required:n = true, item-pos* .dim_gset:N = \g_@@_store_item_symbol_sep_dim, item-pos* .value_required:n = true, print-env .undefine:, store-env .undefine:, write-out .undefine:, unknown .code:n = { \@@_anskey_env_unknown:n {##1} }, } } % \end{macrocode} % The \mymeta{keys} are stored in \cs{l_keys_key_str} and the value % (if any) is passed as an argument to the function \cs{@@_anskey_env_unknown:n}. % \begin{macrocode} \cs_new_protected:Npn \@@_anskey_env_unknown:n #1 { \exp_args:NV \@@_anskey_env_unknown:nn \l_keys_key_str {#1} } \cs_new_protected:Npn \@@_anskey_env_unknown:nn #1#2 { \tl_if_blank:nTF {#2} { \msg_error:nnn { enumext } { anskey-env-key-unknown } {#1} } { \msg_error:nnnn { enumext } { anskey-env-key-value-unknown } {#1} {#2} } } % \end{macrocode} % The function \cs{@@_anskey_env_reset_keys:} will leave the keys % \mykeycmd{break-col}, \mykeycmd{item-join}, \mykeycmd{item-join}, % \mykeycmd{item-star}, \mykeycmd{item-sym*} and \mykeycmd{item-pos*} % undefined. We will apply this function using the \emph{hook} function % \cs{@@_after_env:nn}. % \iffalse %% Restore keys for |scontents| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_env_reset_keys: { \keys_define:nn { scontents / scontents } { break-col .undefine:, item-join .undefine:, item-star .undefine:, item-sym* .undefine:, item-pos* .undefine:, write-out .code:n = { \bool_set_false:N \l__scontents_storing_bool \bool_set_true:N \l__scontents_writing_bool \tl_set:Nn \l__scontents_fname_out_tl {##1} }, write-out .value_required:n = true, print-env .meta:nn = { scontents } { print-env = ##1 }, print-env .default:n = true, store-env .meta:nn = { scontents } { store-env = ##1 }, unknown .code:n = { \__scontents_parse_environment_keys:n {##1} }, } } % \end{macrocode} % The function \cs{@@_rescan_anskey_env:n} will be responsible for % bringing the \mymeta{body} of the environment saved in the sequence % \myvarenv{g__scontents_name_\mymeta[cf=gray]{store name}_seq} to % pass it to our \emph{sequence} and \emph{prop list}. % \begin{macrocode} \cs_new_protected:Npn \@@_rescan_anskey_env:n #1 { \group_begin: \int_set:Nn \tex_newlinechar:D { `\^^J } \__scontents_rescan_tokens:x { \endgroup % This assumes \catcode`\\=0... Things might go off otherwise. #1 } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_anskey_env_exec:,} % The function \cs{@@_anskey_env_exec:} will be responsible for % processing all the code necessary for the execution of the environment. % The first thing will be to add our \mymeta{keys}. % \iffalse %% Function for exec all code for |anskey*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_env_exec: { \@@_before_env:nn { anskey* } { \@@_anskey_env_define_keys: } % \end{macrocode} % Now we will execute our actions after the \myenv*{anskey*} % environment is closed. We'll fetch the contents of the % \emph{environment body} that is now saved in % \myvarenv{g__scontents_name_\mymeta[cf=gray]{store name}_seq} and store it in % the variable \cs{l_@@_store_anskey_env_tl} then we execute the rest of the functions. % \begin{macrocode} \hook_if_empty:nF {env/anskey*/after} { \hook_gremove_code:nn {env/anskey*/after} { * } } \@@_after_env:nn { anskey* } { \@@_anskey_env_save_keys: \tl_clear:N \l_@@_store_anskey_env_tl \tl_clear:N \l_@@_store_anskey_opt_tl \bool_if:NT \l_@@_check_answers_bool { \tl_gset:Ne \l_@@_store_anskey_env_tl { \seq_item:ce { g__scontents_name_ \l_@@_store_name_tl _seq } { -1 } } \regex_match:nVTF { ^\s* \z | ^\s* \u{c__scontents_hidden_space_str} \z } \l_@@_store_anskey_env_tl { \msg_error:nn { enumext } { anskey-empty-arg } } { \@@_anskey_env_store: } } \@@_anskey_env_clean_vars: \@@_anskey_env_reset_keys: } } % \end{macrocode} % \begin{important}* % The use of \cs{hook_gremove_code:nn} is necessary here, otherwise the % \mymarg{code} passed to \cs{@@_after_env:nn}|{anskey*}| will be accumulated % for each execution. % The last function \cs{@@_anskey_env_reset_keys:} is necessary so as % not to hinder any \myenv{scontents} environment running within % \myenv*{enumext} or \myenv*{enumext*}. % \end{important} % \end{macro} % % \begin{macro}[int]{\@@_anskey_env_save_keys:, \@@_anskey_env_store:, % \@@_anskey_env_clean_vars:, } % The function \cs{@@_anskey_env_save_keys:} processing the \myoarg{key \textnormal{\textcolor{gray}{=}} val} % passed to the environment and save this in the variable \cs{l_@@_store_anskey_opt_tl}. % If the \mykeycmd{break-col} key is present and the environment is % running under \myenv*{enumext} (not in \myenv*{enumext*}) % we will add the key \mykeycmd{break-col}. % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_env_save_keys: { \bool_lazy_and:nnT { \bool_if_p:N \g_@@_store_columns_break_bool } { \bool_not_p:n { \l_@@_starred_bool } } { \tl_put_left:Ne \l_@@_store_anskey_opt_tl { ,break-col, } } % \end{macrocode} % If the \mykeycmd{item-join} key is present and the command is running under % \myenv*{enumext*} we will add to \cs{l_@@_store_anskey_opt_tl}. % \begin{macrocode} \bool_lazy_and:nnT { \bool_not_p:n { \l_@@_starred_bool } } { \int_compare_p:nNn { \g_@@_store_item_join_int } > { 1 } } { \tl_put_left::Ne \l_@@_store_anskey_opt_tl { ,item-join = \exp_not:V \g_@@_store_item_join_int, } } % \end{macrocode} % And now we will review the keys \mykeycmd{item-star}, \mykeycmd{item-sym*} and % \mykeycmd{item-pos*} and pass them to \cs{l_@@_store_anskey_opt_tl}. % \begin{macrocode} \bool_if:NT \g_@@_store_item_star_bool { \tl_put_left:Ne \l_@@_store_anskey_opt_tl { ,item-star, } \tl_if_empty:NF \g_@@_store_item_symbol_tl { \tl_put_left:Ne \l_@@_store_anskey_opt_tl { ,item-sym* = \exp_not:V \g_@@_store_item_symbol_tl, } } \dim_compare:nT { \g_@@_store_item_symbol_sep_dim != \c_zero_dim } { \tl_put_left:Ne \l_@@_store_anskey_opt_tl { ,item-pos* = \exp_not:V \g_@@_store_item_symbol_sep_dim, } } } } % \end{macrocode} % The function \cs{@@_anskey_env_store:} will be responsible for storing % the content of the environment using the functions \cs{@@_store_anskey_code:n} % and \cs{@@_rescan_anskey_env:n}. % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_env_store: { \group_begin: \tl_if_empty:NTF \l_@@_store_anskey_opt_tl { \exp_args:Ne \@@_store_anskey_code:n { \@@_rescan_anskey_env:n { \l_@@_store_anskey_env_tl } } } { \keys_set_known:nV { enumext / anskey } \l_@@_store_anskey_opt_tl \exp_args:Ne \@@_store_anskey_code:n { \@@_rescan_anskey_env:n { \l_@@_store_anskey_env_tl } } } \group_end: } % \end{macrocode} % The function \cs{@@_anskey_env_clean_vars:} will return the global % variables used by the \mymeta{keys} to their initial state. % \begin{macrocode} \cs_new_protected:Nn \@@_anskey_env_clean_vars: { \bool_gset_false:N \g_@@_store_columns_break_bool \int_gzero:N \g_@@_store_item_join_int \bool_gset_false:N \g_@@_store_item_star_bool \tl_gclear:N \g_@@_store_item_symbol_tl \dim_gzero:N \g_@@_store_item_symbol_sep_dim } % \end{macrocode} % \end{macro} % % \subsection{Executing \texttt{anskey*}, \texttt{check-ans} and write \texttt{.log}}\label{fun:exec-after-env} % % \begin{macro}{\@@_execute_after_env:} % The \cs{@@_execute_after_env:} function will first return the % appropriate message for the end of the environment in which the % \mykey{save-ans} key is being executed, then call the % \cs{@@_item_answer_diff:} function and then will write the values of % the global variables used to the |.log| file. If the key % \mykey{check-ans} is active it will execute the function % \cs{@@_check_ans_show:} and show the result in the terminal, otherwise % it will execute the function \cs{@@_check_ans_log:} and write the % results in the |.log| file, undefine the environment \myenv*{anskey*} (\S\ref{env:anskey}) % through the function \cs{@@_undefine_anskey_env:} and finally we execute the function % \cs{@@_reset_global_vars:} returning the used variables to their % original state. % \iffalse %% Function internal checking answer mechanism, clean vars and undefine |anskey*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_execute_after_env: { \int_compare:nNnT { \l_@@_level_int } = { 0 } { \tl_if_empty:NF \g_@@_store_name_tl { \@@_stop_save_ans_msg: \@@_item_answer_diff: \@@_log_global_vars: \@@_log_answer_vars: \bool_if:NTF \g_@@_check_ans_key_bool { \@@_check_ans_show: } { \@@_check_ans_log: } \@@_undefine_anskey_env: } \@@_reset_global_vars: } } % \end{macrocode} % \end{macro} % % \begin{important}* % This function is passed to the function \cs{@@_after_env:nn} for the % environments \myenv*{enumext} (\S\ref{env:enumext}) and \myenv*{enumext*} (\S\ref{env:starred}) % and it is executed only when the environments are not nested or at some level of these.. % \end{important} % % \subsection{Common functions for \env{keyans}, \env{keyans*} and \env{keyanspic}} % % \subsubsection{Storing content in prop list} % % \begin{macro}{\@@_keyans_addto_prop:n} % The function \cs{@@_keyans_addto_prop:n} will pass the the current \mymeta{label} for |\item*| % in \myenv*{keyans} environment and the current \mymeta{label} for % |\anspic*| in \myenv*{keyanspic} environment followed by the % \mymeta{contents} of the \emph{optional argument} of both commands % to the \cs{l_@@_store_current_label_tl} variable, which will be stored % to the \emph{prop list} defined by the \mykey{save-ans} key using the % function \cs{@@_store_addto_prop:V}. % \iffalse %% Function for storing in prop list for |keyans| and |keyanspic| environments. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_addto_prop:n #1 { \tl_clear:N \l_@@_store_current_label_tl \int_compare:nNnTF { \l_@@_keyans_pic_level_int } = { 1 } { \tl_put_right:Ne \l_@@_store_current_label_tl { \l_@@_label_vi_tl } } { \tl_put_right:Ne \l_@@_store_current_label_tl { \l_@@_label_v_tl } } % \end{macrocode} % If the \emph{optional argument} is present and the \mykey{save-sep} % key is not empty, we save it. % \begin{macrocode} \tl_if_novalue:nF { #1 } { \tl_if_empty:NF \l_@@_store_keyans_item_opt_sep_tl { \tl_put_right:Ne \l_@@_store_current_label_tl { \l_@@_store_keyans_item_opt_sep_tl } } \tl_put_right:Ne \l_@@_store_current_label_tl { #1 } } \@@_store_addto_prop:V \l_@@_store_current_label_tl } % \end{macrocode} % \end{macro} % % \subsubsection{The \texttt{save-ref} key for \env{keyans}, \env{keyans*} and \env{keyanspic}}\label{fun:save-ref-keyans} % % The \emph{\enquote{internal label and ref}} system for the \myenv*{keyans}, % \myenv*{keyans*} and \myenv*{keyanspic} environments has \emph{slight differences} % with the one implemented for \ics*{anskey} basically because in this % environments the interest is in the current \mymeta{label} for |\item*| % and |\anspic*| with the \mymeta{contents} of the \emph{optional argument}. The mechanism % defined here will allow to execute \ics{ref}\mymarg{store name \textcolor{red}{:} position} and % will return |1.(A)|. % % \begin{macro}{\@@_keyans_store_ref:, \@@_keyans_store_ref_aux_i:, % \@@_keyans_store_ref_aux_ii:,} % The function \cs{@@_keyans_store_ref:} handles the % \emph{\enquote{internal label and ref}} system used by the % \mykey{save-ref} key for \ics*{item*} and \ics*{anspic*} commands. % First we will create copies of the current \mymeta{labels} and remove % the dots \enquote{\textcolor{red}{\texttt{.}}} from them, we do not % want to get double dots in references. % \iffalse %% Internal label and ref function for |keyans|, |keyans*| and |keyanspic| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_store_ref: { \bool_if:NT \l_@@_store_ref_key_bool { \cs_set_protected:Npn \@@_tmp:n ##1 { \tl_set_eq:cc { l_@@_label_copy_##1_tl } { l_@@_label_##1_tl } \tl_reverse:c { l_@@_label_copy_##1_tl } \tl_remove_once:cn { l_@@_label_copy_##1_tl } { . } \tl_reverse:c { l_@@_label_copy_##1_tl } } \clist_map_inline:nn { i, v, vi, vii, viii } { \@@_tmp:n {##1} } \@@_keyans_store_ref_aux_i: } } % \end{macrocode} % The auxiliary function \cs{@@_keyans_store_ref_aux_i:} set the % variable \cs{l_@@_newlabel_arg_one_tl} which will contain % \mymarg{store name \textcolor{red}{:} position} analyzing whether % the environment in which they are executed is \myenv*{enumext*} or % \myenv*{enumext}. % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_store_ref_aux_i: { \bool_if:NT \g_@@_starred_bool { \tl_set_eq:NN \l_@@_label_copy_i_tl \l_@@_label_copy_vii_tl } \int_compare:nNnT { \l_@@_keyans_pic_level_int } = { 1 } { \tl_put_right:Ne \l_@@_newlabel_arg_two_tl { \l_@@_label_copy_i_tl . \l_@@_label_copy_vi_tl } } \int_compare:nNnT { \l_@@_keyans_level_int } = { 1 } { \tl_put_right:Ne \l_@@_newlabel_arg_two_tl { \l_@@_label_copy_i_tl . \l_@@_label_copy_v_tl } } \int_compare:nNnT { \l_@@_keyans_level_h_int } = { 1 } { \tl_put_right:Ne \l_@@_newlabel_arg_two_tl { \l_@@_label_copy_i_tl . \l_@@_label_copy_viii_tl } } \tl_put_right:Ne \l_@@_newlabel_arg_one_tl { \l_@@_store_name_tl \c_colon_str \int_eval:n { \prop_count:c { g_@@_ \l_@@_store_name_tl _prop } } } \@@_keyans_store_ref_aux_ii: } % \end{macrocode} % Now auxiliary function \cs{@@_keyans_store_ref_aux_ii:} save the % result in the variable \cs{l_@@_write_aux_file_tl} and finally we % write in the |.aux| file. % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_store_ref_aux_ii: { \tl_put_right:Ne \l_@@_write_aux_file_tl { \@@_newlabel:nn { \exp_not:V \l_@@_newlabel_arg_one_tl } { \l_@@_newlabel_arg_two_tl } } \l_@@_write_aux_file_tl } % \end{macrocode} % \end{macro} % % \subsubsection{Storing content in sequence} % % \begin{macro}{\@@_keyans_addto_seq:n, \@@_keyans_addto_seq_link:} % The function \cs{@@_keyans_addto_seq:n} will pass the % contents of the current \mymeta{label} \cs{l_@@_label_v_tl} for the % \myenv*{keyans} environment and the \cs{l_@@_label_vi_tl} for the \myenv*{keyanspic} environment when using % \ics*{item*} and \ics*{anspic*}, followed by the \mymeta{contents} of the % \emph{optional argument} of both commands to the \cs{l_@@_store_current_label_tl} % variable to the sequence defined by the \mykey{save-ans} key. % \iffalse %% Function for storing in sequence for |keyans| and |keyanspic| environments. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_addto_seq:n #1 { \tl_clear:N \l_@@_store_current_label_tl \int_compare:nNnTF { \l_@@_keyans_pic_level_int } = { 1 } { \tl_put_right:Ne \l_@@_store_current_label_tl { \item \l_@@_label_vi_tl } } { \tl_put_right:Ne \l_@@_store_current_label_tl { \item \l_@@_label_v_tl } } \tl_if_novalue:nF { #1 } { \tl_if_empty:NF \l_@@_store_keyans_item_opt_sep_tl { \tl_put_right:Ne \l_@@_store_current_label_tl { \l_@@_store_keyans_item_opt_sep_tl } } \tl_put_right:Ne \l_@@_store_current_label_tl { #1 } } \@@_keyans_addto_seq_link: } % \end{macrocode} % Checks if the \mykey{save-ref} key is active along with the % \mypkg{hyperref} package load, if both conditions are met, it will % create the \ics{hyperlink} and then store using the % \cs{@@_store_addto_seq:V} function. % Finally, copy the contents of the variable \cs{l_@@_store_current_label_tl} % into the global variable \cs{g_@@_check_ans_item_tl} to be used % by the function \cs{@@_check_starred_cmd:n} and increment % the value of the integer variable \cs{g_@@_item_anskey_int} handled % by the \mykey{check-ans} key. % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_addto_seq_link: { \bool_lazy_and:nnT { \bool_if_p:N \l_@@_store_ref_key_bool } { \bool_if_p:N \l_@@_hyperref_bool } { \tl_put_right:Ne \l_@@_store_current_label_tl { \hfill \exp_not:N \hyperlink { \exp_not:V \l_@@_newlabel_arg_one_tl } { \exp_not:V \l_@@_mark_ref_sym_tl } } } \@@_store_addto_seq:V \l_@@_store_current_label_tl \bool_if:NT \l_@@_check_answers_bool { \int_gincr:N \g_@@_item_anskey_int } } % \end{macrocode} % \end{macro} % % \subsubsection{The \texttt{show-ans} and \texttt{show-pos} keys for \env{keyans} and \env{keyanspic}} % % The code is very similar to the \ics*{anskey} code, but, if I change % the order of the operations the counter off \mymeta{label} are incorrect. % % \begin{macro}{\@@_keyans_show_left:n,\@@_keyans_show_ans:, \@@_keyans_show_pos:, \@@_keyans_show_item_opt:,} % Common function to show \emph{starred commands} |\item*| and \mymeta{position} of % stored content in \emph{prop list} for \myenv*{keyans} and % \myenv*{keyanspic}. Need add |1| to \myvarenv{g__@@_\mymeta[cf=gray]{store name}_prop} for \mykey{show-pos} key. % \iffalse %% Function for |show-ans| and |show-pos| keys for |keyans| and |keyanspic| environments. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_show_left:n #1 { \tl_if_novalue:nF { #1 } { \tl_set:Ne \l_@@_store_current_opt_arg_tl { #1 } } \bool_if:NT \l_@@_show_answer_bool { \@@_keyans_show_ans: } \bool_if:NT \l_@@_show_position_bool { \@@_keyans_show_pos: } } \cs_new_protected:Nn \@@_keyans_show_item_opt: { \tl_if_empty:NF \l_@@_store_current_opt_arg_tl { \bool_lazy_or:nnT { \bool_if_p:N \l_@@_show_answer_bool } { \bool_if_p:N \l_@@_show_position_bool } { \@@_keyans_wrapper_opt:n { \l_@@_store_current_opt_arg_tl } \c_space_tl } } } \cs_new_protected:Nn \@@_keyans_show_ans: { \bool_if:NT \l_@@_starred_bool { \dim_set_eq:NN \l_@@_labelwidth_i_dim \l_@@_labelwidth_vii_dim \dim_set_eq:NN \l_@@_labelsep_i_dim \l_@@_labelsep_vii_dim } \tl_put_left:Nn \l_@@_label_v_tl { \@@_print_keyans_box:NN \l_@@_labelwidth_i_dim \l_@@_labelsep_i_dim } } \cs_new_protected:Nn \@@_keyans_show_pos: { \bool_if:NT \l_@@_starred_bool { \dim_set_eq:NN \l_@@_labelwidth_i_dim \l_@@_labelwidth_vii_dim \dim_set_eq:NN \l_@@_labelsep_i_dim \l_@@_labelsep_vii_dim } \int_compare:nNnTF { \l_@@_keyans_pic_level_int } = { 1 } { \tl_set:Ne \l_@@_mark_answer_sym_tl { \group_begin: \exp_not:N \normalfont \exp_not:N \footnotesize [ \int_eval:n { \prop_count:c { g_@@_ \l_@@_store_name_tl _prop } } ] \group_end: } } { \tl_set:Ne \l_@@_mark_answer_sym_tl { \group_begin: \exp_not:N \normalfont \exp_not:N \footnotesize [ \int_eval:n { \prop_count:c { g_@@_ \l_@@_store_name_tl _prop } + 1 } ] \group_end: } } \tl_put_left:Nn \l_@@_label_v_tl { \@@_print_keyans_box:NN \l_@@_labelwidth_i_dim \l_@@_labelsep_i_dim } } % \end{macrocode} % \end{macro} % % \subsection{Redefining \cs{item} and \cs{makelabel} in \env{enumext}}\label{env:item-starred-enumext} % % Redefining the |\item| command is not as simple as I thought. This % command works in conjunction with the \ics{makelabel} command so I have % to redefine both of them, in addition to this, we will have to use a % couple of \emph{global} variables to pass the values from one command % to the other. % % \smallskip % % When \emph{labeling} \texttt{PDF} is active |\makelabel| is redefined % as |\hss #1| and the only way to get the \mykey{align} key to work % correctly is to redefine |\makelabel| using |\makebox|. The best way to % implement this is to use the conditional command |\IfDocumentMetadataTF| % to force this redefinition and the dedicated \mykey{mode-box} key to % manually activate it by the user. % % \smallskip % % The \ics*{item} and \ics*{item}\myoarg{custom} commands work in the % usual way on \myenv*{enumext} and we will add \ics*{item*}, \ics*{item*}\myoarg{symbol} and % \ics*{item*}\myoarg{symbol}\myoarg{offset}. % % \begin{macro}[int]{\@@_default_item:n} % First we will see if the \emph{optional argument} is present, if it is NOT % present we will check the state of the variable \cs{l_@@_check_answers_bool} % set by the key \mykey{no-store}, set the boolean variable % \myvarenv{l__@@_wrap_label_X_bool} to \enquote{true} for the key \mykey{wrap-label} % and execute \cs{@@_item_std:w} and the key \mykey{itemindent}, otherwise we will check the state % of the boolean variable \myvarenv{l__@@_wrap_label_opt_X_bool} set % by the key \mykey{wrap-label*} and execute \cs{@@_item_std:w} with % the \emph{optional argument} and the key \mykey{itemindent}. % \iffalse %% Internal function for |\item| whit check-answer mechanism in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_default_item:n #1 { \tl_if_novalue:nTF {#1} { \bool_if:NT \l_@@_check_answers_bool { \int_gincr:N \g_@@_item_number_int \bool_set_true:N \l_@@_item_number_bool } \bool_set_true:c { l_@@_wrap_label_ \@@_level: _bool } \@@_item_std:w \tl_use:c { l_@@_fake_item_indent_ \@@_level: _tl } } { \bool_set_eq:cc { l_@@_wrap_label_ \@@_level: _bool } { l_@@_wrap_label_opt_ \@@_level: _bool } \@@_item_std:w [#1] \tl_use:c { l_@@_fake_item_indent_ \@@_level: _tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}[int]{\@@_starred_item:nn, \@@_item_star_exec:,} % The \ics*{item*}, \ics*{item*}\myoarg{symbol} and \ics*{item*}\myoarg{symbol}\myoarg{offset} % works like the \emph{numbered} |\item|, but placing a \mymeta{symbol} % to the \emph{\enquote{left}} of the \mymeta{label} separated from % it by the value the second \emph{optional argument} \mymeta{offset}. % % \begin{arguments} % \item \myvarenv{l__@@_item_symbol_X_tl} % \item \myvarenv{l__@@_item_symbol_sep_X_dim} % \end{arguments} % % First we will make a copy of \myvarenv{l__@@_item_symbol_X_tl} which is % set by the key \mykey{item-sym*} or passed as \emph{\enquote{first}} \emph{optional argument} in % the global variable \cs{g_@@_item_symbol_aux_tl}, followed by setting the % variable \myvarenv{l__@@_item_symbol_sep_X_dim} set by the key % \mykey{item-pos*} or by the \emph{\enquote{second}} \emph{optional argument}, % then we will see the state of the variable \cs{l_@@_check_answers_bool} % set by the key \mykey{no-store}, set the boolean variable % \myvarenv{l__@@_wrap_label_X_bool} to \enquote{true} for the key \mykey{wrap-label} % and execute \cs{@@_item_std:w} and the key \mykey{itemindent}. % \iffalse %% Internal function for |\item*[symb][sep]| whit check-answer mechanism in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_starred_item:nn #1 #2 { \tl_if_novalue:nTF {#1} { \tl_gset_eq:Nc \g_@@_item_symbol_aux_tl { l_@@_item_symbol_ \@@_level: _tl } } { \tl_gset:Nn \g_@@_item_symbol_aux_tl {#1} } \tl_if_novalue:nTF {#2} { \dim_set_eq:cc { l_@@_item_symbol_sep_ \@@_level: _dim } { l_@@_labelsep_ \@@_level: _dim } } { \dim_set:cn { l_@@_item_symbol_sep_ \@@_level: _dim } {#2} } \bool_if:NT \l_@@_check_answers_bool { \int_gincr:N \g_@@_item_number_int \bool_set_true:N \l_@@_item_number_bool } \bool_set_true:c { l_@@_wrap_label_ \@@_level: _bool } \@@_item_std:w \tl_use:c { l_@@_fake_item_indent_ \@@_level: _tl } } % \end{macrocode} % The function \cs{@@_item_star_exec:} will be responsible for % executing |\item*| for the \myenv*{enumext} environment. % \iffalse %% Function for |\item*[sym][sep]| in |\makelabel| for |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_item_star_exec: { \tl_if_empty:cF { l_@@_item_symbol_ \@@_level: _tl } { \mode_leave_vertical: \skip_horizontal:n { -\dim_use:c { l_@@_item_symbol_sep_ \@@_level: _dim } } \hbox_overlap_left:n { \g_@@_item_symbol_aux_tl } \skip_horizontal:n { \dim_use:c { l_@@_item_symbol_sep_ \@@_level: _dim } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_redefine_item:} % The function \cs{@@_redefine_item:} will redefine the |\item| % command in the \myenv*{enumext} environment adding |\item*|. % This function are passed to \myvarenv{__@@_list_arg_two_X:} used % in the definition of the \myenv*{enumext} environment (\S\ref{env:enumext}). % \iffalse %% Redefinition of |\item| for |\item*[sym][sep]| in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_redefine_item: { \RenewDocumentCommand \item { s o o } { \bool_if:nTF {##1} { \@@_starred_item:nn {##2} {##3} } { \@@_default_item:n {##2} } } } % \end{macrocode} % \end{macro} % % \medskip % % \begin{macro}{\@@_make_label:,\@@_make_label_std:,\@@_make_label_box:} % The function \cs{@@_make_label:} redefine \ics{makelabel} for the keys % \mykey{mode-box}, \mykey{align}, \mykey{font}, \mykey{wrap-label}, % \mykey{wrap-label*} and |\item*| for \myenv*{enumext} environment. % This function are passed to \myvarenv{__@@_list_arg_two_X:} used % in the definition of the \myenv*{enumext} environment (\S\ref{env:enumext}). % \iffalse %% Redefinition of |\makelabel| for |\item| and |\item*[sym][sep]| in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_make_label: { \IfDocumentMetadataTF { \@@_make_label_box: } { \bool_if:NTF \l_@@_mode_box_bool { \@@_make_label_box: } { \@@_make_label_std: } } } % \end{macrocode} % Standard definition when |\DocumentMetadata| is not active. % \begin{macrocode} \cs_new_protected:Nn \@@_make_label_std: { \RenewDocumentCommand \makelabel { m } { \tl_use:c { l_@@_label_fill_left_ \@@_level: _tl } \tl_use:c { l_@@_label_font_style_ \@@_level: _tl } \bool_if:cTF { l_@@_wrap_label_ \@@_level: _bool } { \@@_item_star_exec: \use:c { @@_wrapper_label_ \@@_level: :n } { ##1 } } { ##1 } \tl_use:c { l_@@_label_fill_right_ \@@_level: _tl } \tl_gclear:N \g_@@_item_symbol_aux_tl } } % \end{macrocode} % Definition using |\makebox| when |\DocumentMetadata| is active or % \mykey{mode-box} is active. % % \begin{important} % Here it is necessary to use |\strut\smash| to maintain text \emph{alignment} % in case the user wants to use |\labelbx| for example. In my experiments % with \emph{mimicking} the \myenv{description} environment it was the only way % out and it seems to have no adverse effects and may serve in the future % as a basis for a more generic \myenv{list} environment package than % \mypkg*{enumext}. % \end{important} % % \begin{macrocode} \cs_new_protected:Nn \@@_make_label_box: { \RenewDocumentCommand \makelabel { m } { \strut\smash { \makebox [ \dim_use:c { l_@@_labelwidth_ \@@_level: _dim } ] [ \str_use:c { l_@@_align_label_pos_ \@@_level: _str } ] { \tl_use:c { l_@@_label_font_style_ \@@_level: _tl } \bool_if:cTF { l_@@_wrap_label_ \@@_level: _bool } { \@@_item_star_exec: \use:c { @@_wrapper_label_ \@@_level: :n } { ##1 } } { ##1 } \tl_gclear:N \g_@@_item_symbol_aux_tl } } % close smash } } % \end{macrocode} % \end{macro} % % \subsection{Setting \texttt{item-sym*} and \texttt{item-pos*} keys}\label{key:item-starred} % % In order to have a cleaner implementation of |\item*| for the % \myenv*{enumext} and \myenv*{enumext*} environments it is best to % define a couple of keys that allow us to control and set by default the % \mymeta{symbol} and its \mymeta{offset}. % % \begin{macro}[int]{item-sym*, item-pos*} % Define and set \mykey{item-sym*} and \mykey{item-pos*} keys for % \myenv*{enumext} and \myenv*{enumext*}. % \iffalse %% Add |item-sym*| and |item-sep*| keys. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:nn #1 #2 { \keys_define:nn { enumext / #1 } { item-sym* .tl_set:c = { l_@@_item_symbol_#2_tl }, item-sym* .value_required:n = true, item-sym* .initial:n = {\textasteriskcentered}, item-pos* .dim_set:c = { l_@@_item_symbol_sep_#2_dim }, item-pos* .value_required:n = true, } } \clist_map_inline:nn { {level-1}{i}, {level-2}{ii}, {level-3}{iii}, {level-4}{iv}, {enumext*}{vii} } { \@@_tmp:nn #1 } % \end{macrocode} % \end{macro} % % \subsection{Handling unknown keys}\label{key:unknown-keys} % % At this point in the code I already know that I will not add more % \mymeta{keys} and since I have already been quite \emph{paranoid and % restrictive} with the definitions of environments and commands, the % only thing left to do is do it with the \mymeta{keys} (you have to be % consistent in life). % % \subsubsection{Handling unknown keys for \env{keyans}, \env{keyans*} and \env{keyanspic}}\label{key:unknown-keys-keyans} % % \begin{macro}[int]{unknown, \@@_keyans_unknown_keys:n, \@@_keyans_unknown_keys:nn} % Define and set |unknown| key for \myenv*{keyans}, \myenv*{keyans*} % and \myenv*{keyanspic} environments. % \iffalse %% Add keys |unknown| for |keyans|, |keyans*| and |keyanspic| environments. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { unknown .code:n = { \@@_keyans_unknown_keys:n {##1} } } } \clist_map_inline:nn { keyans, keyans*, keyanspic } { \@@_tmp:n {#1} } % \end{macrocode} % Internal functions for handling |unknown| key. % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_unknown_keys:n #1 { \exp_args:NV \@@_keyans_unknown_keys:nn \l_keys_key_str {#1} } \cs_new_protected:Npn \@@_keyans_unknown_keys:nn #1#2 { \tl_if_blank:nTF {#2} { \msg_error:nnn { enumext } { keyans-unknown-key } {#1} } { \msg_error:nnnn { enumext } { keyans-unknown-key-value } {#1} {#2} } } % \end{macrocode} % \end{macro} % % \subsubsection{Handling unknown keys for \env{enumext*}}\label{key:unknown-keys-starred} % % \begin{macro}[int]{unknown, \@@_starred_unknown_keys:n, \@@_starred_unknown_keys:nn} % Define and set |unknown| key for \myenv*{enumext*} environment. % \iffalse %% Add keys |unknown| for |enumext*| environment. % \fi % \begin{macrocode} \keys_define:nn { enumext / enumext* } { unknown .code:n = { \@@_starred_unknown_keys:n {#1} } } % \end{macrocode} % Internal functions for handling |unknown| key. % \begin{macrocode} \cs_new_protected:Npn \@@_starred_unknown_keys:n #1 { \exp_args:NV \@@_starred_unknown_keys:nn \l_keys_key_str {#1} } \cs_new_protected:Npn \@@_starred_unknown_keys:nn #1#2 { \tl_if_blank:nTF {#2} { \msg_error:nnn { enumext } { starred-unknown-key } {#1} } { \msg_error:nnnn { enumext } { starred-unknown-key-value } {#1} {#2} } } % \end{macrocode} % \end{macro} % % \subsubsection{Handling unknown keys for \env{enumext}}\label{key:unknown-keys-standar} % % \begin{macro}[int]{unknown, \@@_standar_unknown_keys:n, \@@_standar_unknown_keys:nn} % Defines and set the key |unknown| for \myenv*{enumext} environment. % \iffalse %% Add keys |unknown| for |enumext| environment. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \keys_define:nn { enumext / #1 } { unknown .code:n = { \@@_standar_unknown_keys:n {##1} } } } \clist_map_inline:nn { level-1,level-2,level-3,level-4 } { \@@_tmp:n {#1} } % \end{macrocode} % Internal functions for handling |unknown| key. % \begin{macrocode} \cs_new_protected:Npn \@@_standar_unknown_keys:n #1 { \exp_args:NV \@@_standar_unknown_keys:nn \l_keys_key_str {#1} } \cs_new_protected:Npn \@@_standar_unknown_keys:nn #1#2 { \tl_if_blank:nTF {#2} { \msg_error:nnn { enumext } { standar-unknown-key } {#1} } { \msg_error:nnnn { enumext } { standar-unknown-key-value } {#1} {#2} } } % \end{macrocode} % \end{macro} % % \subsection{Redefining \cs{item} and \cs{makelabel} in \env{keyans}}\label{cmd:item-starred} % % The \ics*{item} and \ics*{item}\myoarg{custom} commands work in the % usual way in \myenv*{keyans}, but the \ics*{item*} and \ics*{item*}\myoarg{content} % commands \emph{store} the current \mymeta{label} next to the \mymeta{content} % if it is present in the \emph{sequence} and \emph{prop list} defined by % \mykey{save-ans} key. % % \begin{macro}{\@@_keyans_default_item:n,} % The function \cs{@@_keyans_default_item:n} executes the original % behavior of the \ics*{item} along with the keys \mykey{wrap-label}, % \mykey{wrap-label*} and \mykey{itemindent}. % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_default_item:n #1 { \tl_if_novalue:nTF { #1 } { \bool_set_true:N \l_@@_wrap_label_v_bool \@@_item_std:w \tl_use:N \l_@@_fake_item_indent_v_tl } { \bool_set_eq:NN \l_@@_wrap_label_v_bool \l_@@_wrap_label_opt_v_bool \@@_item_std:w [#1] \tl_use:N \l_@@_fake_item_indent_v_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_keyans_starred_item:n} % The function \cs{@@_keyans_starred_item:n} which will make a temporary % copy of the current \mymeta{label}, execute the \mykey{show-ans} % or \mykey{show-pos} keys using the function \cs{@@_keyans_show_left:n} % and will display the \mymeta{contents} of that item using the internal % copy \cs{@@_item_std:w}, this is necessary to prevent incrementing % the current \emph{\enquote{counter}} of the original \mymeta{label}, % followed by this it will execute function \cs{@@_keyans_show_item_opt:} % handled by \mykey{wrap-opt} key. % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_starred_item:n #1 { \tl_set_eq:NN \l_@@_store_current_label_tmp_tl \l_@@_label_v_tl \@@_keyans_show_left:n { #1 } \bool_set_true:N \l_@@_wrap_label_v_bool \@@_item_std:w \tl_use:N \l_@@_fake_item_indent_v_tl \@@_keyans_show_item_opt: % \end{macrocode} % Recover the original value of the current \mymeta{label} and \emph{store} % it first in the \emph{prop list} (including the \emph{optional argument}), % run the internal \emph{\enquote{label and ref}} system if the % \mykey{save-ref} key is active, \emph{store} it in the \emph{sequence} % and finally increments \cs{g_@@_check_starred_cmd_int} for internal % check system. % \begin{macrocode} \tl_set_eq:NN \l_@@_label_v_tl \l_@@_store_current_label_tmp_tl \@@_keyans_addto_prop:n { #1 } \@@_keyans_store_ref: \@@_keyans_addto_seq:n { #1 } \int_gincr:N \g_@@_check_starred_cmd_int } % \end{macrocode} % \end{macro} % % \begin{macro}{\item*,\@@_keyans_redefine_item:} % The function \cs{@@_keyans_redefine_item:} is responsible for adding % the \emph{starred argument} and \emph{optional argument} by the % \cs{@@_list_arg_two_v:} function in the definition of the % \myenv*{keyans} environment. Here we need to use % |\peek_remove_spaces:n| to prevent an unwanted space when using % |\item*| in conjunction with the \mykey{itemindent} key. % This function are passed to \myvarenv{__@@_list_arg_two_v:} used % in the definition of the \myenv*{keyans} environment (\S\ref{ltx:second-arg}). % \iffalse %% Redefine |\item| for |keyans| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_redefine_item: { \RenewDocumentCommand \item { s o } { \bool_if:nTF {##1} { \peek_remove_spaces:n { \@@_keyans_starred_item:n {##2} } } { \@@_keyans_default_item:n {##2} } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_keyans_make_label:,\@@_keyans_make_label_std:,\@@_keyans_make_label_box:} % The function \cs{@@_keyans_make_label:} redefine \ics{makelabel} % for the keys \mykey{mode-box}, \mykey{align}, \mykey{font}, % \mykey{wrap-label}, \mykey{wrap-label*} and |\item*| for \myenv*{keyans} % environment. % This function are passed to \myvarenv{__@@_list_arg_two_v:} used % in the definition of the \myenv*{keyans} environment (\S\ref{ltx:second-arg}). % \iffalse %% Redefine |\makelabel| for |keyans| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_make_label: { \IfDocumentMetadataTF { \@@_keyans_make_label_box: } { \bool_if:NTF \l_@@_mode_box_bool { \@@_keyans_make_label_box: } { \@@_keyans_make_label_std: } } } % \end{macrocode} % Standard definition when |\DocumentMetadata| is not active. % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_make_label_std: { \RenewDocumentCommand \makelabel { m } { \tl_use:N \l_@@_label_fill_left_v_tl \tl_use:N \l_@@_label_font_style_v_tl \bool_if:NTF \l_@@_wrap_label_v_bool { \@@_wrapper_label_v:n { ##1 } } { ##1 } \tl_use:N \l_@@_label_fill_right_v_tl } } % \end{macrocode} % Definition using |\makebox| when |\DocumentMetadata| is active or % \mykey{mode-box} is active. % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_make_label_box: { \RenewDocumentCommand \makelabel { m } { \strut\smash { \makebox[ \l_@@_labelwidth_v_dim ][ \l_@@_align_label_pos_v_str ] { \tl_use:N \l_@@_label_font_style_v_tl \bool_if:NTF \l_@@_wrap_label_v_bool { \@@_wrapper_label_v:n { ##1 } } { ##1 } } } } } % \end{macrocode} % \end{macro} % % \subsection{Second argument of the lists}\label{ltx:second-arg} % % At this point of the code we have already programmed most the necessary % tools to create a custom \myenv{list} environment, remember that the function % \cs{@@_start_list:nn} takes two arguments, the first one we have % ready, the second one we will define for all the levels of the % environment \myenv*{enumext} and the environment \myenv*{keyans}. % % \subsubsection{Calculation of \cs{leftmargin} and \cs{itemindent}}\label{int:leftmargin} % % Consider the figure \ref{fig:eight} where the default margins (on the % left) of a list are represented. % % \begin{figure}[!htbp] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (-0.5,6.175) --node[below,text=lightgray,font=\footnotesize\ttfamily]{margin page} (2,6.175); % \draw[line width=0.5pt,dash pattern=on 2pt off 2pt,color=gray] (2,4.85) -- (2,7.5); % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{list-offset}} (4.5,7.0); % \draw[<->,color=gray] (4.5,7.0) --node[above,text=blue!75]{\vphantom{p}\texttt{\textbackslash{}labelwidth}} (7.5,7.0); % \draw[<->,color=gray] (7.5,7.0) --node[above,text=blue!75]{\texttt{\textbackslash{}labelsep}} (9.5,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (4.5,6.5) rectangle (7.5,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.5,6.5) rectangle (9.5,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.5) rectangle (15,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.0) rectangle (15,6.35); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,5.5) rectangle (15,5.85); % \draw[<->,color=gray] (1.25,5.35) --node[below,text=blue!75]% % {\begin{tabular}{c} % \texttt{\textbackslash{}leftmargin + \textbackslash{}itemindent} \\ % \textcolor{optcolor}{\texttt{list-indent}} % \end{tabular}} (9.5,5.35); % \end{tikzpicture} % \caption{Representation of standard horizontal lengths in \myenv{list} environment.} % \label{fig:eight} % \end{figure} % % The idea is to have control over these margins so that our list does % not overlap the left margin of the page. The \emph{key} relationship is that % the right edge of the |\labelsep| equals the right edge of the |\itemindent|, % so that the left edge of the \emph{label box} is at |\leftmargin+\itemindent| minus |\labelwidth+\labelsep|. % Thus, the handling of the margins by the package will be as shown in % the figure \ref{fig:nine}. % % \begin{figure}[!htbp] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (-0.5,6.175) --node[below,text=lightgray,font=\footnotesize\ttfamily]{margin page} (2,6.175); % \draw[line width=0.5pt,dash pattern=on 2pt off 2pt,color=gray] (2,4.85) -- (2,7.5); % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{list-offset}} (4.5,7.0); % \draw[<->,color=gray] (4.5,7.0) --node[above,text=blue!75]{\vphantom{p}\texttt{\textbackslash{}labelwidth}} (7.5,7.0); % \draw[<->,color=gray] (7.5,7.0) --node[above,text=blue!75]{\texttt{\textbackslash{}labelsep}} (9.5,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (4.5,6.5) rectangle (7.5,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.5,6.5) rectangle (9.5,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.5) rectangle (15,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,6.0) rectangle (15,6.35); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (9.5,5.5) rectangle (15,5.85); % \draw[<->,color=gray] (4.5,5.35) --node[below,text=blue!75]% % {\begin{tabular}{c} % \texttt{\textbackslash{}leftmargin + \textbackslash{}itemindent} \\ % \textcolor{optcolor}{\texttt{list-indent}} % \end{tabular}} (9.5,5.35); % \end{tikzpicture} % \caption{Representation of horizontal lengths concept in list in \mypkg*{enumext}.} % \label{fig:nine} % \end{figure} % % Where the default values will look like in the figure \ref{fig:last}. % % \begin{figure}[htbp] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % \draw[<->,color=gray] (-0.5,6.175) --node[below,text=lightgray,font=\footnotesize\ttfamily]{margin page} (2,6.175); % \draw [line width=0.5pt,dash pattern=on 2pt off 2pt,color=gray] (2,4.85) -- (2,7.5); % \draw[<->,color=gray] (2.0,7.0) --node[above,text=blue!75]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=blue!75]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (15,6.85);% item width % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.0) rectangle (15,6.35); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.5) rectangle (15,5.85); % \draw[<->,color=gray] (2.0,5.35) --node[below,text=blue!75]% % {\begin{tabular}{c} % \texttt{\textbackslash{}leftmargin + \textbackslash{}itemindent} \\ % \textcolor{optcolor}{\texttt{list-indent}} % \end{tabular}} % (7.0,5.35); % \end{tikzpicture} % \caption{Default horizontal lengths in \mypkg*{enumext}.} % \label{fig:last} % \end{figure} % % \begin{macro}{\@@_calc_hspace:NNNNNNN, \@@_calc_hspace:ccccccc} % The function \cs{@@_calc_hspace:NNNNNNN} takes seven arguments to be % able to determine horizontal spaces for all list environment: % % \begin{verbatim} % #1: \l__enumext_labelwidth_X_dim #2: \l__enumext_labelsep_X_dim % #3: \l__enumext_listoffset_X_dim #4: \l__enumext_leftmargin_tmp_X_dim % #5: \l__enumext_leftmargin_X_dim #6: \l__enumext_itemindent_X_dim % #7: \l__enumext_leftmargin_tmp_X_bool % \end{verbatim} % % And returns the \emph{\enquote{adjusted}} values of |\leftmargin| % and |\itemindent|. % % \smallskip % % This function is passed to \myvarenv{__@@_list_arg_two_X:} which % is used in the definition of the \myenv*{enumext} and \myenv*{keyans} % environments (\S\ref{ltx:second-arg}). % \iffalse %% Function to calc of horizontal length for all list environment. %% #1: \l__enumext_labelwidth_X_dim #2: \l__enumext_labelsep_X_dim %% #3: \l__enumext_listoffset_X_dim #4: \l__enumext_leftmargin_tmp_X_dim %% #5: \l__enumext_leftmargin_X_dim #6: \l__enumext_itemindent_X_dim %% #7: \l__enumext_leftmargin_tmp_X_bool % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_calc_hspace:NNNNNNN #1 #2 #3 #4 #5 #6 #7 { \dim_compare:nNnT { #1 } < { \c_zero_dim } { \msg_warning:nnnV { enumext } { width-non-positive }{ labelwidth }{ #1 } \dim_set:Nn #1 { \dim_abs:n { #1 } } } \dim_compare:nNnT { #2 } < { \c_zero_dim } { \msg_warning:nnnV { enumext } { width-negative }{ labelsep }{ #2 } \dim_set:Nn #2 { \dim_abs:n { #2 } } } % \end{macrocode} % If no value has been passed to the \mykey{labelwidth} and \mykey{labelsep} keys we % set the default values for \myvarenv{l__@@_leftmargin_tmp_X_dim}. % \begin{macrocode} \bool_if:nF #7 { \dim_set:Nn #4 { #1 + #2} } % \end{macrocode} % We now analyze the cases and set the values for \ics{leftmargin} and % \ics{itemindent}. % \begin{macrocode} \dim_compare:nNnTF { #4 } < { \c_zero_dim } { \dim_set:Nn #6 { #1 + #2 - #4} \dim_set:Nn #5 { #1 + #2 + #3 - #6 } } { \dim_compare:nNnT { #4 } = { #1 + #2 } { \dim_set:Nn #6 { \c_zero_dim } } \dim_compare:nNnT { #4 } < { #1 + #2 } { \dim_set:Nn #6 { #1 + #2 - #4} } \dim_compare:nNnT { #4 } > { #1 + #2 } { \dim_set:Nn #6 { -#1 - #2 + #4} \dim_set:Nn #6 { #6*-1} } \dim_set:Nn #5 { #1 + #2 + #3 - #6 } } } \cs_generate_variant:Nn \@@_calc_hspace:NNNNNNN { ccccccc } % \end{macrocode} % \end{macro} % % \subsubsection{Setting second argument of the lists} % % \begin{macro}{\@@_list_arg_two_i:,\@@_list_arg_two_ii:,\@@_list_arg_two_iii:, % \@@_list_arg_two_iv:,\@@_list_arg_two_v:,} % We will \enquote{not set} |\leftmargini|, |\leftmarginii|, |\leftmarginiii| or % |\leftmarginiv|, in this case, we will directly set the parameters % for vertical and horizontal list spacing per level. % \iffalse %% Define "second arg" of list for |enumext| and |keyans|. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \cs_new_protected:cpn { @@_list_arg_two_#1: } { \@@_calc_hspace:ccccccc { l_@@_labelwidth_#1_dim } { l_@@_labelsep_#1_dim } { l_@@_listoffset_#1_dim } { l_@@_leftmargin_tmp_#1_dim } { l_@@_leftmargin_#1_dim } { l_@@_itemindent_#1_dim } { l_@@_leftmargin_tmp_#1_bool } \clist_map_inline:nn { labelsep, labelwidth, itemindent, leftmargin, rightmargin, listparindent } { \dim_set_eq:cc {####1} { l_@@_####1_#1_dim } } \clist_map_inline:nn { topsep, parsep, partopsep, itemsep } { \skip_set_eq:cc {####1} { l_@@_####1_#1_skip } } \usecounter { enumX#1 } \setcounter { enumX#1 } { \int_eval:n { \int_use:c { l_@@_start_#1_int } - 1 } } \str_if_eq:nnTF {#1} { v } { \@@_keyans_redefine_item: \@@_keyans_make_label: \@@_keyans_ref: \@@_keyans_fake_item_indent: \bool_if:cT { l_@@_show_length_#1_bool } { \msg_term:nnnn { enumext } { list-lengths-not-nested } { v } { keyans } } } { \@@_redefine_item: \@@_make_label: \@@_standar_ref: \@@_fake_item_indent: \bool_if:cT { l_@@_show_length_#1_bool } { \msg_term:nnne { enumext } { list-lengths } {#1} { \int_use:N \l_@@_level_int } } } } } \clist_map_inline:nn { i, ii, iii, iv, v } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_list_arg_two_vii:,\@@_list_arg_two_viii:,} % For the horizontal environments \myenv*{enumext*} and \myenv*{keyans*} % the implementation is similar, but, the value of |\partopsep| is always % \mydim{0pt}. At this point we will modify the \mykey{parsep} key to % make it take the value of the \mykey{itemsep} key and later, in the % environment definition, we will modify \mykey{parindent} to make it set % the value of \mykey{lisparindent} and \mykey{parsep} to set the value % of |\parskip| locally. % \iffalse %% Define "second arg" of list for |enumext*| and |keyans*|. % \fi % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:n #1 { \cs_new_protected:cpn { @@_list_arg_two_#1: } { \bool_set_true:c { l_@@_leftmargin_tmp_#1_bool } \dim_zero:c { l_@@_leftmargin_tmp_#1_dim } \@@_calc_hspace:ccccccc { l_@@_labelwidth_#1_dim } { l_@@_labelsep_#1_dim } { l_@@_listoffset_#1_dim } { l_@@_leftmargin_tmp_#1_dim } { l_@@_leftmargin_#1_dim } { l_@@_itemindent_#1_dim } { l_@@_leftmargin_tmp_#1_bool } \clist_map_inline:nn { labelsep, labelwidth, itemindent, leftmargin, rightmargin, listparindent } { \dim_set_eq:cc {####1} { l_@@_####1_#1_dim } } \clist_map_inline:nn { topsep, parsep, partopsep, itemsep } { \skip_set_eq:cc {####1} { l_@@_####1_#1_skip } } \skip_set_eq:Nc \parsep { l_@@_itemsep_#1_skip } \skip_zero:N \partopsep \usecounter { enumX#1 } \setcounter { enumX#1 } { \int_eval:n { \int_use:c { l_@@_start_#1_int } - 1 } } \@@_starred_ref: \str_if_eq:nnTF {#1} { vii } { \@@_fake_item_indent_vii: \bool_if:cT { l_@@_show_length_vii_bool } { \msg_term:nnnn { enumext } { list-lengths-not-nested } { vii } { enumext* } } } { \@@_fake_item_indent_viii: \bool_if:cT { l_@@_show_length_#1_bool } { \msg_term:nnnn { enumext } { list-lengths-not-nested } { #1 } { keyans* } } } } } \clist_map_inline:nn { vii, viii } { \@@_tmp:n {#1} } % \end{macrocode} % \end{macro} % % \subsection{The environment \env{enumext}}\label{env:enumext} % % \begin{macro}{\@@_safe_exec:}\label{fun:enumext:safe-exe} % The \cs{@@_safe_exec:} function first call the function \cs{@@_is_not_nested:} % which sets \cs{g_@@_standar_bool} to \emph{\enquote{true}} if we % are NOT nested within \myenv*{enumext*}, then call the function % \cs{@@_internal_mini_page:} to create the environment \myvarenv*{__@@_mini_page}, % we will increment \cs{l_@@_level_int} to restrict nesting of the % environment, set \cs{l_@@_standar_bool} to \emph{\enquote{true}} and % finally call the function \cs{@@_is_on_first_level:} which sets % \cs{l_@@_standar_first_bool} to \emph{\enquote{true}} only if the % environment is NOT nested and we are at the \emph{\enquote{first level}}. % \iffalse %% Safe exec for |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_safe_exec: { \@@_is_not_nested: \@@_internal_mini_page: \int_incr:N \l_@@_level_int \int_compare:nNnT { \l_@@_level_int } > { 4 } { \msg_fatal:nn { enumext } { list-too-deep } } \bool_set_true:N \l_@@_standar_bool \bool_set_false:N \l_@@_starred_bool \@@_is_on_first_level: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_keys:n} % The \cs{@@_parse_store_keys:n} function first we will clear the % variable \cs{l_@@_series_str} used by the key \mykey{series} and then % we check if we are at the \emph{\enquote{first level}}, if so we % process the \mymeta{keys} and then execute the function % \cs{@@_parse_series:n} used by the key \mykey{series} and call the % function \cs{@@_nested_base_line_fix:} used by the key % \mykey{base-fix}, otherwise we will pass the \mymeta{keys} to the inner % levels of the environment then we execute the function \cs{@@_store_active_keys:n} % and reprocess the \mymeta{keys} to pass them to the \emph{sequence} % if the key \mykey{save-key} is not active. % \iffalse %% Parse |key=val| and set default series and store keys in seq-name for \printkeyans for |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_parse_keys:n #1 { \tl_if_novalue:nF {#1} { \str_clear:N \l_@@_series_str \int_compare:nNnTF { \l_@@_level_int } = { 1 } { \keys_set:nn { enumext / level-1 } {#1} \@@_parse_series:n {#1} \@@_nested_base_line_fix: } { \exp_args:Ne \keys_set:nn { enumext / level-\int_use:N \l_@@_level_int } {#1} } \@@_store_active_keys:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_start_store_level:} % The \cs{@@_start_store_level:} function activate the \emph{\enquote{storing structure}} % mechanism in the \emph{sequence} for the command % \ics*{anskey} and the environment \myenv*{anskey*}. % \iffalse %% Start storing structure in sequence for |save-ans| key in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_start_store_level: { \bool_lazy_all:nT { { \bool_if_p:N \l_@@_store_active_bool } { \bool_not_p:n { \l_@@_keyans_env_bool } } { \bool_if_p:N \g_@@_standar_bool } } { \int_compare:nNnT { \l_@@_level_int } > { 1 } { \bool_set_true:c { l_@@_store_upper_level_ \@@_level: _bool } \@@_store_level_open: } } % \end{macrocode} % If \myenv*{enumext} are nested in \myenv*{enumext*} add \cs{@@_store_level_open:} % to preserve the \emph{\enquote{storing structure}}. % \begin{macrocode} \bool_lazy_all:nT { { \bool_if_p:N \l_@@_store_active_bool } { \bool_not_p:n { \l_@@_keyans_env_bool } } { \int_compare_p:nNn { \l_@@_level_h_int } = { 1 } } } { \int_compare:nNnT { \l_@@_level_int } > { 0 } { \bool_set_true:c { l_@@_store_upper_level_ \@@_level: _bool } \@@_store_level_open: } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_stop_store_level:} % The \cs{@@_stop_store_level:} function stop the \emph{\enquote{storing structure}} % mechanism in the \emph{sequence} for the command % \ics*{anskey} and the environment \myenv*{anskey*}. % \iffalse %% Stop storing structure in sequence for |save-ans| key in |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_stop_store_level: { \bool_if:cT { l_@@_store_upper_level_ \@@_level: _bool } { \@@_store_level_close: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_multicols_start:} % The function \cs{@@_multicols_start:} will start the % \myenv{multicols} environment according to the value passed by the % \mykey{columns} key, then set the default value for % \ics{columnsep} when \mykey{columns-sep}=\mydim{0pt} and set the % value of \ics{multicolsep} equal to zero and leave \ics{columnseprule} % equal to zero for inner levels. % \begin{macrocode} \cs_new_protected:Nn \@@_multicols_start: { \int_compare:nNnT { \int_use:c { l_@@_columns_ \@@_level: _int } } > { 1 } { \dim_compare:nNnT { \dim_use:c { l_@@_columns_sep_ \@@_level: _dim } } = { \c_zero_dim } { \dim_set:cn { l_@@_columns_sep_ \@@_level: _dim } { ( \dim_use:c { l_@@_labelwidth_ \@@_level: _dim } + \dim_use:c { l_@@_labelsep_ \@@_level: _dim } ) / \int_use:c { l_@@_columns_ \@@_level: _int } - \dim_use:c { l_@@_listoffset_ \@@_level: _dim } } } \dim_set_eq:Nc \columnsep { l_@@_columns_sep_ \@@_level: _dim } \int_compare:nNnT { \l_@@_level_int } > { 1 } { \dim_zero:N \columnseprule } % \end{macrocode} % We will calculate the \emph{vertical spacing} settings for the % \myenv{multicols} environment using the function \cs{@@_multi_addvspace:}, % apply our \emph{\enquote{vertical adjust spacing}}, then start the % \myenv{multicols} environment. % \begin{macrocode} \bool_if:cF { l_@@_minipage_active_ \@@_level: _bool } { \skip_zero:N \multicolsep \@@_multi_addvspace: } \raggedcolumns \begin{multicols}{ \int_use:c { l_@@_columns_ \@@_level: _int } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_multicols_stop:} % The function \cs{@@_multicols_stop:} will stop the \myenv{multicols} % environment and apply our \emph{\enquote{vertical adjust}} spacing. % For compatibility with \emph{tagged} \texttt{PDF}, the closing of the % \myenv{list} environment is executed here along with \cs{@@_stop_store_level:}. % \begin{macrocode} \cs_new_protected:Nn \@@_multicols_stop: { \int_compare:nNnTF { \int_use:c { l_@@_columns_ \@@_level: _int } } > { 1 } { \@@_stop_list: \@@_stop_store_level: \end{multicols} \@@_unskip_unkern: \@@_unskip_unkern: \par\addvspace{ \skip_use:c { l_@@_multicols_below_ \@@_level: _skip } } } { \@@_stop_list: \@@_stop_store_level: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_before_list:} % The function \cs{@@_before_list:} first calls the function % \cs{@@_vspace_above:} used by the keys \mykey{above} and % \mykey{above*}, then calls the function \cs{@@_before_args_exec:} % used by the key \mykey{before*} and finally execute the function % \cs{@@_check_ans_active:} for the check answer mechanism. % \begin{macrocode} \cs_new_protected:Nn \@@_before_list: { \@@_vspace_above: \@@_before_args_exec: \@@_check_ans_active: % \end{macrocode} % When the \mykey{mini-env} key is active it will set the value of the % \myvarenv{l__@@_minipage_right_X_dim} to be the \emph{width} of the \myvarenv*{__@@_mini_page} % environment on the \emph{\enquote{right side}}, using this value together with the value % of the \myvarenv{l__@@_minipage_hsep_X_dim} set by the \mykey{mini-sep} key, % the value of \myvarenv{l__@@_minipage_left_X_dim} will be set, which will be % the \emph{width} of \myvarenv*{__@@_mini_page} environment on the % \emph{\enquote{left side}}, always having a current \ics{linewidth} % as \emph{maximum width} between them. % \iffalse %% Set |mini-env| width value. % \fi % \begin{macrocode} \dim_compare:nNnT { \dim_use:c { l_@@_minipage_right_ \@@_level: _dim } } > { \c_zero_dim } { \dim_set:cn { l_@@_minipage_left_ \@@_level: _dim } { \linewidth - \dim_use:c { l_@@_minipage_right_ \@@_level: _dim } - \dim_use:c { l_@@_minipage_hsep_ \@@_level: _dim } } % \end{macrocode} % The boolean variable \myvarenv{l__@@_minipage_active_X_bool} will be % activated and the integer variable \cs{g_@@_minipage_stat_int} % used by the \ics*{miniright} command will be incremented, then % the function \cs{@@_minipage_add_space:} is called and the % \myvarenv*{__@@_mini_page} environment on the \emph{\enquote{left % side}} will be initialized followed by the \emph{\enquote{vertical spacing}} % applied to preserve the \emph{\enquote{baseline}} between the \emph{left} % and \emph{right} side environments. % After these actions, the function \cs{@@_multicols_start:} is % called to handle the \myenv{multicols} environment. % \iffalse %% Use internal minipage with |\nointerlineskip| and |\addvspace| here % \fi % \begin{macrocode} \bool_set_true:c { l_@@_minipage_active_ \@@_level: _bool } \int_gincr:N \g_@@_minipage_stat_int \@@_minipage_add_space: \noindent \@@_mini_page{ \dim_use:c { l_@@_minipage_left_ \@@_level: _dim } } } \@@_multicols_start: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_second_part:} % The function \cs{@@_second_part:} first check the state of % the boolean variable \myvarenv{l__@@_minipage_active_X_bool}, if it is % \enquote{true} a small test will be executed to check if we have % omitted the use of \ics*{miniright} (the \myvarenv*{__@@_mini_page} % environment has not been closed), then close \myvarenv*{__@@_mini_page} % and add the \emph{adjusted vertical space} \cs{l_@@_minipage_after_skip}, % otherwise we will close the \myenv{multicols} environment. % \begin{macrocode} \cs_new_protected:Nn \@@_second_part: { \bool_if:cTF { l_@@_minipage_active_ \@@_level: _bool } { \int_compare:nNnT { \g_@@_minipage_stat_int } = { 1 } { \msg_warning:nn { enumext } { missing-miniright } \miniright } \int_gzero:N \g_@@_minipage_stat_int \@@_unskip_unkern: % remove topsep + [partopsep] \end@@_mini_page } { \@@_multicols_stop: } % \end{macrocode} % Now we will execute the functions \cs{@@_after_stop_list:} used by % the key \mykey{after}, \cs{@@_check_ans_key_hook:} used by the key % \mykey{check-ans}, \cs{@@_vspace_below:} used by the keys \mykey{below} % and \mykey{below*}. Finally set \cs{l_@@_standar_bool} to false and call % the function \cs{@@_resume_save_counter:} used by the \mykey{series}, % \mykey{resume} and \mykey{resume*} keys. % \begin{macrocode} \@@_after_stop_list: \@@_check_ans_key_hook: \@@_vspace_below: \bool_set_false:N \l_@@_standar_bool \@@_resume_save_counter: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_item_width:}\label{dim:item-width-enumext} % The function \cs{@@_set_item_width:} will set the value of |\itemwidth| % taking into account the value established by the \mykey{list-offset} % key for each level of the environment. % \iffalse %% Set |\itemwidth| for |enumext| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_set_item_width: { \dim_set:Nn \itemwidth { \linewidth } \dim_compare:nT { \dim_use:c { l_@@_listoffset_ \_@@_level: _dim } != \c_zero_dim } { \dim_sub:Nn \itemwidth { \dim_use:c { l_@@_listoffset_ \_@@_level: _dim } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{enumext} % Now create the \myenv*{enumext} environment based on \myenv{list} % environment by levels. % \iffalse %% Definition of |enumext| environment. % \fi % \begin{macrocode} \NewDocumentEnvironment{enumext}{ O{} } { \@@_safe_exec: \@@_parse_keys:n {#1} \@@_before_list: \@@_start_store_level: \@@_start_list:nn { \tl_use:c { l_@@_label_ \@@_level: _tl } } { \use:c { @@_list_arg_two_ \@@_level: : } \@@_before_keys_exec: } \@@_set_item_width: \@@_after_args_exec: } { \@@_second_part: } % \end{macrocode} % \end{macro} % % As we don't want our check to be executed \mykey{check-ans} by levels % but on the complete list, we will take it out of the \myenv*{enumext} % environment using the \emph{\enquote{hook}} function \cs{@@_after_env:nn}. % \iffalse %% Execute |check-ans| key out of |enumext| environment. % \fi % \begin{macrocode} \@@_after_env:nn {enumext} { \@@_execute_after_env: } % \end{macrocode} % % \subsection{The environment \env{keyans}}\label{env:keyans} % % The environment \myenv*{keyans} also based on lists. % The main differences with the \myenv*{enumext} environment are the % \emph{nesting} and the way the \emph{answers} (choice) will be stored and checked, this % environment is intended exclusively for \emph{\enquote{multiple choice questions}}. % % \begin{macro}{\@@_keyans_safe_exec:} % The \myenv*{keyans} environment will only be available if the % \mykey{save-ans} key is active and can only be used at the % \emph{\enquote{first level}} within the \myenv*{enumext} environment. % We do not want the environment to be nested, so we will set a maximum at this point. % If the conditions are not met, an error message will be returned. % \iffalse %% Function for check nested level in |keyans| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_safe_exec: { \bool_if:NF \l_@@_store_active_bool { \msg_error:nnnn { enumext } { wrong-place }{ keyans }{ save-ans } } \int_incr:N \l_@@_keyans_level_int \bool_set_true:N \l_@@_keyans_env_bool \@@_keyans_name_and_start: % Set false for interfering with enumext nested in keyans (yes, its possible and crayze) \bool_set_false:N \l_@@_store_active_bool \int_compare:nNnT { \l_@@_keyans_level_int } > { 1 } { \msg_error:nn { enumext } { keyans-nested } } \int_compare:nNnT { \l_@@_level_int } > { 1 } { \msg_error:nn { enumext } { keyans-wrong-level } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_keyans_parse_keys:n} % Parse \myoarg{key \textnormal{\textcolor{gray}{=}} val} for % \myenv*{keyans} environment. % \iffalse %% Function for parse |key=val| in |keyans|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_parse_keys:n #1 { \keys_set:nn { enumext / keyans } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_before_list_v:, \@@_keyans_multicols_start:, % \@@_keyans_multicols_stop:, \@@_second_part_v:} % Same implementation as the one used in the \myenv*{enumext} environment. % \iffalse %% Internal functions for |keyans| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_before_list_v: { \@@_vspace_above_v: \@@_before_args_exec_v: \dim_compare:nNnT { \l_@@_minipage_right_v_dim } > { \c_zero_dim } { \dim_set:Nn \l_@@_minipage_left_v_dim { \linewidth - \l_@@_minipage_right_v_dim - \l_@@_minipage_hsep_v_dim } \bool_set_true:N \l_@@_minipage_active_v_bool \int_gincr:N \g_@@_minipage_stat_int \@@_keyans_minipage_add_space: \@@_mini_page{ \l_@@_minipage_left_v_dim } } \@@_keyans_multicols_start: } \cs_new_protected:Nn \@@_keyans_multicols_start: { \int_compare:nNnT { \l_@@_columns_v_int } > { 1 } { \dim_compare:nNnT { \l_@@_columns_sep_v_dim } = { \c_zero_dim } { \dim_set:Nn \l_@@_columns_sep_v_dim { ( \l_@@_labelwidth_v_dim + \l_@@_labelsep_v_dim ) / \l_@@_columns_v_int - \l_@@_listoffset_v_dim } } \dim_set_eq:NN \columnsep \l_@@_columns_sep_v_dim \dim_zero:N \columnseprule % no rule here \bool_if:NF \l_@@_minipage_active_v_bool { \skip_zero:N \multicolsep \@@_keyans_multi_addvspace: } \raggedcolumns \begin{multicols}{ \l_@@_columns_v_int } } } \cs_new_protected:Nn \@@_keyans_multicols_stop: { \int_compare:nNnTF { \l_@@_columns_v_int } > { 1 } { \@@_stop_list: \end{multicols} \@@_unskip_unkern: \@@_unskip_unkern: \par\addvspace{ \l_@@_multicols_below_v_skip } } { \@@_stop_list: } } \cs_new_protected:Nn \@@_second_part_v: { \bool_if:NTF \l_@@_minipage_active_v_bool { \int_compare:nNnT { \g_@@_minipage_stat_int } = { 1 } { \msg_warning:nn { enumext } { missing-miniright } \miniright } \int_gzero:N \g_@@_minipage_stat_int \@@_unskip_unkern: % remove \topsep + [\partopsep] \end@@_mini_page \par\addvspace{ \l_@@_minipage_after_skip } } { \@@_keyans_multicols_stop: } \bool_set_false:N \l_@@_keyans_env_bool \@@_after_stop_list_v: \@@_vspace_below_v: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_keyans_set_item_width:}\label{dim:item-width-keyans} % The function \cs{@@_keyans_set_item_width:} will set the value of |\itemwidth| % taking into account the value established by the \mykey{list-offset} % key. % \iffalse %% Set |\itemwidth| for |keyans| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_set_item_width: { \dim_set:Nn \itemwidth { \linewidth } \dim_compare:nT { \l_@@_listoffset_v_dim != \c_zero_dim } { \dim_sub:Nn \itemwidth { \l_@@_listoffset_v_dim } } } % \end{macrocode} % \end{macro} % % \begin{macro}{keyans} % Now we define the environment \myenv*{keyans} also based on lists. % \iffalse %% Definition of |keyans| environment. % \fi % \begin{macrocode} \NewDocumentEnvironment{keyans}{ O{} } { \@@_keyans_safe_exec: \@@_keyans_parse_keys:n {#1} \@@_before_list_v: \@@_start_list:nn { \tl_use:N \l_@@_label_v_tl } { \@@_list_arg_two_v: \@@_before_keys_exec_v: } \@@_keyans_set_item_width: \@@_after_args_exec_v: } { \@@_check_starred_cmd:n { item } \@@_second_part_v: } % \end{macrocode} % \end{macro} % % \subsection{Tagging PDF support for non-standart list environments}\label{ltx:tag-nonestandarlist} % % The \hologo{LaTeX} release 2022-06-01 brings automatic support for % \emph{tagged} \texttt{PDF} in several aspects, including the standard \emph{list environments} % and the \myenv{list} environment. Unfortunately non-standard \emph{list environments} % like \myenv*{keyanspic} or the horizontal list environments % \myenv*{enumext*} and \myenv*{keyans*} are not structured in a nice % way, i.e. the expected result in the \texttt{PDF} file is the expected % one, but the underlying structure is not correct. In simple terms, for % \emph{tagged} \texttt{PDF} a \myenv{list} environment is a \myenv{list} environment, no matter % what it looks like in the \texttt{PDF} file. % % \smallskip % % To maintain a correct \myenv{list} structure when |\DocumentMetadata| is % active, it is necessary to do some things manually using % \mypkg{tagpdf}\cite{tagpdf} and \mypkg{ltsockets}\cite{ltsockets}. % This implementation is an adaptation of my answer thanks to Ulrike Fischer's % comments in \href{https://tex.stackexchange.com/a/725902}{How can I modify my \texttt{\textbackslash item} redefinition to be compatible with \texttt{tagging-pdf}}. % % \subsubsection{Socket for tagging support in \env{enumext*} and \env{keyans*}} % % \begin{macro}[int]{start-list-tags, stop-start-tags, stop-list-tags, % \@@_start_list_tag:n,\@@_stop_start_list_tag:, % \@@_stop_list_tag:n} % We will first define the necessary \texttt{sockets} and their % behavior for \myenv*{enumext*} and \myenv*{keyans*}. % \iffalse %% Implement socket for tagging support in |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \socket_new:nn {tagsupport/@@/starred}{ 1 } \socket_new_plug:nnn {tagsupport/@@/starred} {start-list-tags} { \tag_resume:n {#1} \tag_mc_end_push: \tag_struct_begin:n {tag=LI} \tag_struct_begin:n {tag=Lbl} \tag_mc_begin:n {tag=Lbl} } \socket_new_plug:nnn {tagsupport/@@/starred} {stop-start-tags} { \tag_mc_end: \tag_struct_end:n {tag=Lbl} \tag_struct_begin:n {tag=LBody} \tag_struct_begin:n {tag=text-unit} \tag_struct_begin:n {tag=text} } \socket_new_plug:nnn {tagsupport/@@/starred} {stop-list-tags} { \tag_struct_end:n {tag=text} \tag_struct_end:n {tag=text-unit} \tag_struct_end:n {tag=LBody} \tag_struct_end:n {tag=LI} \tag_mc_begin_pop:n {} \tag_suspend:n {#1} } % \end{macrocode} % % And now we'll wrap them so that they're only active when |\DocumentMetadata| is present. % \iffalse %% Wrap socket in conditional functions for tagging |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_start_list_tag:n #1 { \IfDocumentMetadataTF { \socket_assign_plug:nn {tagsupport/@@/starred} {start-list-tags} \socket_use:nn {tagsupport/@@/starred} {#1} } {} } \cs_new_protected_nopar:Nn \@@_stop_start_list_tag: { \IfDocumentMetadataTF { \socket_assign_plug:nn {tagsupport/@@/starred} {stop-start-tags} \socket_use:nn {tagsupport/@@/starred} { } } {} } \cs_new_protected_nopar:Npn \@@_stop_list_tag:n #1 { \IfDocumentMetadataTF { \socket_assign_plug:nn {tagsupport/@@/starred} {stop-list-tags} \socket_use:nn {tagsupport/@@/starred} {#1} } {} } % \end{macrocode} % \end{macro} % % \subsubsection{Socket for tagging support in \env{keyanspic}} % % \begin{macro}[int]{start-list-tags, stop-start-tags, stop-list-tags, % \@@_anspic_start_list_tag:,\@@_anspic_stop_start_list_tag:, % \@@_anspic_stop_list_tag:} % We will first define the necessary \texttt{sockets} and their % behavior for \myenv*{keyanspic} environment. % \iffalse %% Implement socket for tagging support in |keyanspic| environment. % \fi % \begin{macrocode} \socket_new:nn {tagsupport/@@/keyanspic}{ 0 } \socket_new_plug:nnn {tagsupport/@@/keyanspic} {start-list-tags} { \tag_resume:n {keyanspic} \tag_mc_end_push: \tag_struct_begin:n {tag=LI} \tag_struct_begin:n {tag=Lbl} \tag_mc_begin:n {tag=Lbl} } \socket_new_plug:nnn {tagsupport/@@/keyanspic} {stop-start-tags} { \tag_mc_end: \tag_struct_end:n {tag=Lbl} \tag_struct_begin:n {tag=LBody} \tag_struct_begin:n {tag=text-unit} \tag_struct_begin:n {tag=text} \tag_mc_begin:n {tag=text} } \socket_new_plug:nnn {tagsupport/@@/keyanspic} {stop-list-tags} { \tag_mc_end: \tag_struct_end:n {tag=text} \tag_struct_end:n {tag=text-unit} \tag_struct_end:n {tag=LBody} \tag_struct_end:n {tag=LI} \tag_mc_begin_pop:n {} \tag_suspend:n {keyanspic} } % \end{macrocode} % And now we'll wrap them so that they're only active when % |\DocumentMetadata| is present. % \iffalse %% Wrap socket in conditional functions for tagging |keyanspic| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_anspic_start_list_tag: { \IfDocumentMetadataTF { \socket_assign_plug:nn {tagsupport/@@/keyanspic} {start-list-tags} \socket_use:n {tagsupport/@@/keyanspic} } {} } \cs_new_protected_nopar:Nn \@@_anspic_stop_start_list_tag: { \IfDocumentMetadataTF { \socket_assign_plug:nn {tagsupport/@@/keyanspic} {stop-start-tags} \socket_use:n {tagsupport/@@/keyanspic} } {} } \cs_new_protected_nopar:Nn \@@_anspic_stop_list_tag: { \IfDocumentMetadataTF { \socket_assign_plug:nn {tagsupport/@@/keyanspic} {stop-list-tags} \socket_use:n {tagsupport/@@/keyanspic} } {} } % \end{macrocode} % \end{macro} % % \subsection{The environment \env{keyanspic} and \cs{anspic}} % % The \myenv*{keyanspic} environment is a \myenv{list} based environment that % uses the same configuration for \emph{\enquote{spacing}} and \mymeta{label} % as the \myenv*{keyans} environment, but it does not use |\item|. % The \mymeta{contents} are passed to the environment by means of the % \ics*{anspic} command as replacement for |\item| command and placed % inside \myenv{minipage} environments, with the \mymeta{label} % centered \emph{\enquote{above}} or \emph{\enquote{below}}, adjusting % \emph{widths} and \emph{position} according to the options passed to % the environment. % % \begin{figure}[ht] % \centering % \begin{tikzpicture}[line cap=round,line join=round,x=0.8cm,y=0.8cm,every node/.style={font=\footnotesize}] % % space above % \draw[color=white] (7.0,6.10) rectangle (17.5,6.5) node[pos=.5,text=black]% % { \textcolor{optcolor}{\texttt{layout-top}} }; % % space between % \draw[color=white] (7.0,4.5) rectangle (17.5,4.9) node[pos=.5,text=black]% % { \textcolor{optcolor}{\texttt{layout-sep}} }; % % space below % \draw[color=white] (7.0,2.9) rectangle (17.5,3.3) node[pos=.5,text=black]% % { \textcolor{optcolor}{\texttt{layout-top}} }; % % labelwidth % \draw[<->,color=gray] (2.0,7.0) --node[above,text=optcolor]{\vphantom{p}\texttt{labelwidth}} (5.0,7.0); % \draw[<->,color=gray] (5.0,7.0) --node[above,text=optcolor]{\texttt{labelsep}} (7.0,7.0); % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,6.5) rectangle (5.0,6.85);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,6.5) rectangle (7.0,6.85);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,6.5) rectangle (17.5,6.85);% item width % % minipage one % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,5.25) rectangle (10.5,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage one} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % % label one % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,4.9) rectangle (10.5,5.25) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % % minipage two % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (10.5,5.25) rectangle (14,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage two} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % % label two % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (10.5,4.9) rectangle (14,5.25) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % % minipage three % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (14,5.25) rectangle (17.5,6.10) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage three} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % % label three % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (14,4.9) rectangle (17.5,5.25) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % % minipage four % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,3.65) rectangle (12.25,4.5) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage four} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % % label four % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,3.3) rectangle (12.25,3.65) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % % minipage five % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (12.25,3.65) rectangle (17.5,4.5) node[pos=.5,text=black]% % {\begin{tabular}{c} % \texttt{minipage five} \\ % \textcolor{blue}{\emph{drawing or tabular}} % \end{tabular}}; % % label five % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (12.25,3.3) rectangle (17.5,3.65) node[pos=.5,text=black]% % { \textcolor{blue}{\texttt{label}} }; % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (2.0,2.55) rectangle (5.0,2.9);% labelwidth % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (5.0,2.55) rectangle (7.0,2.9);% labelsep % \draw[color=lightgray,fill=lightgray,fill opacity=0.15] (7.0,2.55) rectangle (17.5,2.9);% item width % \end{tikzpicture} % \caption{Representation of the \myenv*{keyanspic} spacing in \mypkg*{enumext}.} % \label{fig:keyanspic} % \end{figure} % % \smallskip % % In order for the \myenv*{keyanspic} environment and the |\anspic| % command to work correctly, we need to set and export some variables in % the first part of the environment definition and pass them to |\anspic| % which is executed in the second part of the environment. This % implementation is adapted from the answer given by Enrico Gregorio % (\texttt{@egreg}) in \href{https://tex.stackexchange.com/a/577705/7832}{How to process the body of an environment and divide it by a \textbackslash macro?}. % % \subsubsection{The environment \env{keyanspic}}\label{env:keyanspic} % % \begin{macro}[int]{label-pos, label-sep, layout-sty, layout-sep, % layout-top,} % First we define the key that allows us to process the position of the % \mymeta{label} centered \enquote{above} or \enquote{below} which will be \mykey{label-pos}, % the vertical separation of these from \emph{drawing or tabular} will be % handled with the key \mykey{label-sep}. % The \emph{\enquote{layout style}} will be handled with the key % \mykey{layout-sty} will take two values ​​separated by comma \mymarg{n° % upper, n° lower} and will determine the number of \myenv{minipage} % environments in which all arguments of |\anspic| will be printed at the % \enquote{upper} and \enquote{lower} within the environments separated % by the value of the key \mykey{layout-sep}. The vertical space % \enquote{top} and \enquote{bottom} of the environment will be handled % with the key \mykey{layout-top}. % \iffalse %% Add keys for |keyanspic| environment. % \fi % \begin{macrocode} \keys_define:nn { enumext / keyanspic } { label-pos .choice:, label-pos / above .code:n = \bool_set_true:N \l_@@_anspic_label_above_bool \str_set:Nn \l_@@_anspic_mini_pos_str { t }, label-pos / below .code:n = \bool_set_false:N \l_@@_anspic_label_above_bool \str_set:Nn \l_@@_anspic_mini_pos_str { b }, label-pos / unknown .code:n = \msg_error:nneee { enumext } { unknown-choice } { label-pos } { above,~ below } { \exp_not:n {#1} }, label-pos .initial:n = below, label-pos .value_required:n = true, label-sep .skip_set:N = \l_@@_anspic_label_sep_skip, label-sep .value_required:n = true, layout-sty .tl_set:N = \l_@@_anspic_layout_style_tl, layout-sty .value_required:n = true, layout-sep .code:n = \keys_set:nn { enumext / keyans } { parsep = #1 }, layout-sep .value_required:n = true, layout-top .code:n = \keys_set:nn { enumext / keyans } { topsep = #1 }, layout-top .value_required:n = true, unknown .code:n = { \@@_keyans_unknown_keys:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_keyans_pic_safe_exec:, \@@_keyans_pic_parse_keys:n, % \@@_keyans_pic_skip_abs:N, \@@_keyans_pic_arg_two:,} % The function \cs{@@_keyans_pic_safe_exec:} check the nested level % position inside the \myenv*{enumext} environment. % \iffalse %% Internal check code for |keyanspic| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_keyans_pic_safe_exec: { \int_incr:N \l_@@_keyans_pic_level_int \int_compare:nNnT { \l_@@_keyans_pic_level_int } > { 1 } { \msg_error:nn { enumext } { keyanspic-nested } } \@@_keyans_name_and_start: } % \end{macrocode} % Parse \myoarg{key \textnormal{\textcolor{gray}{=}} val} for % \myenv*{keyanspic} environment. % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_pic_parse_keys:n #1 { \tl_if_novalue:nF {#1} { \keys_set:nn { enumext / keyanspic } {#1} } } % \end{macrocode} % The function \cs{@@_keyans_pic_skip_abs:N} will return a positive % value \ics{parsep} from \myenv*{keyans} environment. % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_pic_skip_abs:N #1 { \dim_compare:nNnT { #1 } < { \c_zero_dim } { \skip_set:Nn #1 { -#1 } } } % \end{macrocode} % The \cs{@@_keyans_pic_arg_two:} function will be used in the % \emph{second argument} of the \myenv{list} environment that defines % the \myenv*{keyanspic} environment, with this we will take the % configuration of the \emph{\enquote{spaces}} and the keys % \mykey{label}, \mykey{wrap-label}, \mykey{parsep} and \mykey{topsep} % from the \myenv*{keyans} environment. % The first thing we need to do is set the boolean variable % \cs{l_@@_leftmargin_tmp_v_bool} handled by the \mykey{list-indent} key % to \enquote{false}, then copy the definition of the second list argument % from the \myenv*{keyans} environment definition and make sure that % |\parsep| does not have a negative value. % \begin{macrocode} \cs_new_protected:Npn \@@_keyans_pic_arg_two: { \bool_set_false:N \l_@@_leftmargin_tmp_v_bool \@@_list_arg_two_v: \@@_keyans_pic_skip_abs:N \parsep % \end{macrocode} % Now we increment the counter |enumXv| of the \myenv*{keyans} environment % and save the \emph{total height} of the \mymeta{label} in % \cs{l_@@_anspic_label_htdp_dim} used by |\anspic| and we will adjust % the values ​​of |\parsep| only if the key \mykey{label-pos} is set to \emph{below}. % \begin{macrocode} \bool_if:NF \l_@@_anspic_label_above_bool { \stepcounter { enumXv } \hbox_set:Nn \l_@@_anspic_label_box { \l_@@_label_v_tl } \dim_set:Nn \l_@@_anspic_label_htdp_dim { \box_ht_plus_dp:N \l_@@_anspic_label_box } \skip_add:Nn \parsep { \l_@@_anspic_label_htdp_dim + \box_dp:N \strutbox + \l_@@_anspic_label_sep_skip } } % \end{macrocode} % Finally we \emph{adjust} the value of |\leftmargin| and |\topsep| % then set |\listparindent|, |\partopsep| and |\itemsep| to zero so that % the \emph{horizontal} and \emph{vertical} space is not affected. % \begin{macrocode} \dim_add:Nn \leftmargin { -\labelwidth - \labelsep } \skip_add:Nn \topsep { 0.5\box_dp:N \strutbox } \dim_zero:N \listparindent \skip_zero:N \partopsep \skip_zero:N \itemsep } % \end{macrocode} % \end{macro} % % \begin{macro}{keyanspic} % Now we define the environment \myenv*{keyanspic}. For compatibility % with \emph{tagged} \texttt{PDF} we must use the |\begin{|\myenv{list}|}| % form and a lot of conditional code using |\IfDocumentMetadataTF|. % We will first stop the code for automatic \emph{tagged} \texttt{PDF} % for \myenv{list} environments, redefine |\item| so that it cannot be % used, and stop the code for automatic \emph{tagged} \texttt{PDF} for % the \myenv*{keyanspic} environment. % \iffalse %% Define |keyanspic| environment. % \fi % \begin{macrocode} \NewDocumentEnvironment{keyanspic}{ o } { \@@_keyans_pic_safe_exec: \@@_keyans_pic_parse_keys:n {#1} \begin{list} { } { \@@_keyans_pic_arg_two: } \IfDocumentMetadataTF { \tag_suspend:n {list} }{} \item[] \scan_stop: \RenewDocumentCommand \item {} { \msg_error:nn { enumext } { keyanspic-item-cmd } } \IfDocumentMetadataTF { \tag_resume:n {keyanspic} \tag_tool:n {para/tagging=false} \tag_suspend:n {keyanspic} } { } } % \end{macrocode} % In the second part of the environment definition we will manually place % our code for \emph{tagged} \texttt{PDF} and execute the command % |\anspic| using the \cs{@@_anspic_exec:} function. % \begin{macrocode} { \IfDocumentMetadataTF { \tag_resume:n {keyanspic} \tag_mc_end_push: \tag_struct_begin:n {tag=L,attribute=enumerate} } { } \@@_anspic_exec: \IfDocumentMetadataTF { \tag_suspend:n {keyanspic} } { } \end{list} \IfDocumentMetadataTF { \tag_struct_end:n {tag=L} \tag_mc_begin_pop:n {} \tag_struct_end:n {tag=L} \tag_mc_begin_pop:n {} } { } % \end{macrocode} % Finally we check if \ics*{anspic*} has been used, set the counter |enumXvi| % to zero and apply our \enquote{adjusted} vertical space bottom. % \begin{macrocode} \@@_check_starred_cmd:n { anspic } \setcounter { enumXvi } { 0 } \bool_if:NTF \l_@@_anspic_label_above_bool { \par\addvspace{ 0.5\box_dp:N \strutbox } } { \par \addvspace { \dim_eval:n { \l_@@_anspic_label_htdp_dim + \box_ht_plus_dp:N \strutbox + \l_@@_anspic_label_sep_skip + \l_@@_topsep_v_skip } } } } % \end{macrocode} % \end{macro} % % \subsubsection{The command \cs{anspic}}\label{cmd:anspic} % The \ics*{anspic} command take three arguments, the \emph{starred versions} \ics*{anspic*}\myoarg{content} % \emph{store} the current \mymeta{label} next to the \emph{optional argument} % \myoarg{content} in the \emph{sequence} and \emph{prop list} % defined by \mykey{save-ans} key. The third \emph{mandatory argument} % \mymarg{drawing or tabular} is NOT \emph{stored} in the \emph{sequence} or % \emph{prop list}. % % \begin{important} % One of the complications here to make the \myenv*{keyanspic} % environment compatible with \emph{tagged} PDF is the position of % \mymeta{label}, the \ics*{anspic} command processes the arguments in % order, where |#1| and |#2| correspond to \mymeta{label} and |#3| to the % mandatory argument and puts all this inside a \myenv{minipage} % environment. If |#1| and |#2|, that is \mymeta{label}, is above |#3| % there are no problems with \emph{tagged} PDF, but if |#3| comes first % the list created with \emph{tagged} PDF will not be correct. % \end{important} % % \begin{macro}{\anspic, \@@_anspic_body_dim:n, \@@_anspic_label:nn, % \@@_anspic_label_pos:nnn, \@@_anspic_args:nnn, % \@@_anspic_print:n, \@@_anspic_print:e, \@@_anspic_print:V, % \@@_anspic_row:n, @@_anspic_exec:,} % We check that the command is active in the \myenv*{keyanspic} % environment only if the \mykey{save-ans} key is present, otherwise % we return an error. % The three arguments are handled by the function \cs{@@_anspic_args:nnn} % and stored in the sequence \cs{l_@@_anspic_args_seq} which is processed % by the \myenv*{keyanspic} environment. % \iffalse %% Define |\anspic| for |keyanspic| environment. % \fi % \begin{macrocode} \NewDocumentCommand \anspic { s o +m } { \bool_if:NF \l_@@_store_active_bool { \msg_error:nnnn { enumext } { wrong-place }{ keyanspic }{ save-ans } } \int_compare:nNnT { \l_@@_level_int } > { 1 } { \msg_error:nn { enumext } { keyanspic-wrong-level } } \int_compare:nNnT { \l_@@_keyans_level_int } = { 1 } { \msg_error:nnnn { enumext } { command-wrong-place }{ anspic }{ keyans } } \seq_put_right:Nn \l_@@_anspic_args_seq { \@@_anspic_args:nnn { #1 } { #2 } { #3 } } } % \end{macrocode} % The \cs{@@_anspic_body_dim:n} function will set the value of % \cs{l_@@_anspic_body_htdp_dim} equal to the \enquote{height plus depth} % of the \emph{mandatory argument} if the key \mykey{label-pos} is set % \enquote{below}. % \iffalse %% Set the height plus depth off body arg in dim var for |\anspic|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_anspic_body_dim:n #1 { \bool_if:NF \l_@@_anspic_label_above_bool { \IfDocumentMetadataTF { \tag_suspend:n {keyanspic} } { } \vbox_set:Nn \l_@@_anspic_body_box { #1 } \dim_set:Nn \l_@@_anspic_body_htdp_dim { \box_ht_plus_dp:N \l_@@_anspic_body_box } \IfDocumentMetadataTF { \tag_resume:n {keyanspic} } { } } } % \end{macrocode} % The \cs{@@_anspic_label:nn} function will process inside |\makebox| the % \emph{starred argument} ‘|*|’ and \emph{optional argument} passed % to the command. Here we will store the \mymeta{label} and % \emph{optional argument} in \emph{prop list} and \emph{sequence} % and execute the \mykey{show-ans}, \mykey{show-pos}, \mykey{font}, % \mykey{wrap-label} and \mykey{wrap-opt} keys. % \iffalse %% Process and store label and [opt] for |\anspic|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_anspic_label:nn #1 #2 { \makebox[ \l_@@_anspic_mini_width_dim ][ c ] { \bool_if:nT { #1 } { \@@_keyans_addto_prop:n { #2 } \@@_keyans_store_ref: \@@_keyans_addto_seq:n { #2 } \int_gincr:N \g_@@_check_starred_cmd_int \bool_lazy_or:nnT { \bool_if_p:N \l_@@_show_answer_bool } { \bool_if_p:N \l_@@_show_position_bool } { \tl_set_eq:NN \l_@@_label_v_tl \l_@@_label_vi_tl \@@_keyans_show_left:n { #2 } \tl_set_eq:NN \l_@@_label_vi_tl \l_@@_label_v_tl } } \tl_use:N \l_@@_label_font_style_v_tl \@@_wrapper_label_v:n { \l_@@_label_vi_tl } \@@_keyans_show_item_opt: } } % \end{macrocode} % The function \cs{@@_anspic_label_pos:nnn} will be in charge of % handling the \emph{\enquote{counter}} and the position of the \mymeta{label}, % set by \mykey{label-pos} key which will have the same configuration % as the \myenv*{keyans} environment. % \iffalse %% Set position of labels for |\anspic|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_anspic_label_pos:nnn #1 #2 #3 { \stepcounter { enumXvi } \@@_anspic_body_dim:n { #3 } \bool_if:NTF \l_@@_anspic_label_above_bool { \@@_anspic_label:nn { #1 } { #2 } } { \raisebox { -\dim_eval:n { \l_@@_anspic_label_htdp_dim + \l_@@_anspic_body_htdp_dim + \box_dp:N \strutbox + \l_@@_anspic_label_sep_skip } } [ 0pt ] [ 0pt ] { \@@_anspic_label:nn { #1 } { #2 } } } } % % \end{macrocode} % The \cs{@@_anspic_args:nnn} function will be responsible for placing % the code compatible with \emph{tagged} \texttt{PDF} and the arguments % within the \cs{l_@@_anspic_args_seq} sequence which will be processed % by the \cs{@@_anspic_print:n} function in the second part of the % definition of the \myenv*{keyanspic} environment. % \iffalse %% Process all code for |\anspic| with tagging PDF support. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_anspic_args:nnn { \@@_anspic_start_list_tag: \@@_anspic_label_pos:nnn { #1 } { #2 } { #3 } \@@_anspic_stop_start_list_tag: \bool_if:NTF \l_@@_anspic_label_above_bool { \\[\l_@@_anspic_label_sep_skip] #3 } { \\ #3 } \@@_anspic_stop_list_tag: } % \end{macrocode} % The value \mymarg{n° upper, n° lower} passed to the \mykey{layout-sty} % key is split by comma and is handled directly by the function % \cs{@@_anspic_print:n} and passed to the function \cs{@@_anspic_row:n}. % \begin{macrocode} \cs_new_protected:Nn \@@_anspic_print:n { \clist_map_function:nN { #1 } \@@_anspic_row:n } \cs_generate_variant:Nn \@@_anspic_print:n { e, V } % \end{macrocode} % The function \cs{@@_anspic_row:n} will set the \emph{widths} for the % \myenv{minipage} environments and place \emph{all arguments} passed % to |\anspic| \emph{saved} in the \cs{l_@@_anspic_args_seq} sequence % inside them. % \begin{macrocode} \cs_new_protected:Nn \@@_anspic_row:n { \dim_set:Nn \l_@@_anspic_mini_width_dim { \linewidth / #1 } \int_set:Nn \l_@@_anspic_above_int { \l_@@_anspic_below_int } \int_set:Nn \l_@@_anspic_below_int { \l_@@_anspic_above_int + #1 } \int_step_inline:nnn { \l_@@_anspic_above_int + 1 } { \l_@@_anspic_below_int } { \IfDocumentMetadataTF { \tag_suspend:n {minipage} } { } \begin{minipage}[ \l_@@_anspic_mini_pos_str ]{ \l_@@_anspic_mini_width_dim } \centering \seq_item:Nn \l_@@_anspic_args_seq { ##1 } \end{minipage} \IfDocumentMetadataTF { \tag_resume:n {minipage} } { } } \par } % \end{macrocode} % The \cs{@@_anspic_exec:} function will execute all the code in the % |\anspic| command in the second argument of the |keyanspic| environment % definition. If the key \mykey{layout-sty} is not set, everything will % be printed on a \emph{single line}. % \begin{macrocode} \cs_new_protected:Nn \@@_anspic_exec: { \tl_if_empty:NTF \l_@@_anspic_layout_style_tl { \@@_anspic_print:e { \seq_count:N \l_@@_anspic_args_seq } } { \@@_anspic_print:V \l_@@_anspic_layout_style_tl } } % \end{macrocode} % \end{macro} % % \subsection{The horizontal environments}\label{env:horizontal} % % Generating \emph{horizontal list environments} is NOT as simple as standard % \hologo{LaTeX} list environments. The fundamental part of the code is adapted % from the \mypkg{shortlst} package to a more modern version using \mypkg{expl3}. % It is not possible to redefine |\item| and \ics{makelabel} using |\RenewDocumentCommand| as in % the vertical \emph{non starred} versions. % % \smallskip % % To achieve the \emph{horizontal list environments} we will capture the |\item| % command and the \mymeta{content} of this in \emph{horizontal box} using \ics{makebox} for % the \mykey{label} and a \myenv{minipage} environment for the \mymeta{content} passed to % |\item|, we will also add the \emph{optional argument} \myparg{number} to |\item| % to be able to \emph{join columns} horizontally, in simple terms, we want % |\item| to behave in the same way as in the \myenv*{enumext} environment but % adding an \emph{first optional argument} \myparg{number}. % % \smallskip % % A side effect is the limitation of using |\item| in this way \emph{without} % using |\RenewDocumentCommand|, which loses the original definition and % affects the \emph{standard list environments} provided by \hologo{LaTeX} % and any environment defined using base \myenv{list} environment, including: % \myenv{itemize}, \myenv{enumerate}, \myenv{description}, \myenv{quote}, % \myenv{quotation}, \myenv{verse}, \myenv{center}, \myenv{flushleft}, % \myenv{flushright}, \myenv{verbatim}, \myenv{tabbing}, \myenv{trivlist}, % \myenv{list} and all environments created with |\newtheorem|. % % \smallskip % % \begin{important}* % One way to get around this is to use something like: % % \begin{Verbatim} % \AddToHook{env/enumerate/before}{recover original \item definition} % \end{Verbatim} % % inside \myenv{minipage}, but in my partial tests this does not have the % desired effect and the vertical and horizontal spacing is distorted. % For now this will remain as a limitation and I will see if it is % feasible to implement it in the future. % \end{important} % % \smallskip % % \begin{important} % For compatibility with the \emph{tagged} \texttt{PDF} we close % the environments according to the presence or not of the \mykey{mini-env} key. % \end{important} % % \subsubsection{Functions for item box width} % % \begin{macro}{\@@_starred_columns_set_vii:, \@@_starred_columns_set_viii:,} % We set the default value for the \emph{width of the box} containing the % \mymeta{content} of the items for \myenv*{enumext*} environment. % \iffalse %% Define default item width (columns width) for |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_starred_columns_set_vii: { \dim_compare:nNnT { \l_@@_columns_sep_vii_dim } = { \c_zero_dim } { \dim_set:Nn \l_@@_columns_sep_vii_dim { ( \l_@@_labelwidth_vii_dim + \l_@@_labelsep_vii_dim ) / \l_@@_columns_vii_int } } \int_set:Nn \l_@@_tmpa_vii_int { \l_@@_columns_vii_int - 1 } \dim_set:Nn \l_@@_item_width_vii_dim { ( \linewidth - \l_@@_columns_sep_vii_dim * \l_@@_tmpa_vii_int ) / \l_@@_columns_vii_int - \l_@@_labelwidth_vii_dim - \l_@@_labelsep_vii_dim } % \end{macrocode} % When the key \mykey{rightmargin} is active we must adjust the values. % \begin{macrocode} \dim_compare:nNnT { \l_@@_rightmargin_vii_dim } > { \c_zero_dim } { \dim_sub:Nn \l_@@_item_width_vii_dim { ( \l_@@_rightmargin_vii_dim * \l_@@_tmpa_vii_int ) / \l_@@_columns_vii_int } \dim_add:Nn \l_@@_columns_sep_vii_dim { \l_@@_rightmargin_vii_dim } } } % \end{macrocode} % Same implementation for the \myenv*{keyans*} environment. % \begin{macrocode} \cs_new_protected:Nn \@@_starred_columns_set_viii: { \dim_compare:nNnT { \l_@@_columns_sep_viii_dim } = { \c_zero_dim } { \dim_set:Nn \l_@@_columns_sep_viii_dim { ( \l_@@_labelwidth_viii_dim + \l_@@_labelsep_viii_dim ) / \l_@@_columns_viii_int } } \int_set:Nn \l_@@_tmpa_viii_int { \l_@@_columns_viii_int - 1 } \dim_set:Nn \l_@@_item_width_viii_dim { ( \linewidth - \l_@@_columns_sep_viii_dim * \l_@@_tmpa_viii_int ) / \l_@@_columns_viii_int - \l_@@_labelwidth_viii_dim - \l_@@_labelsep_viii_dim } \dim_compare:nNnT { \l_@@_rightmargin_viii_dim } > { \c_zero_dim } { \dim_sub:Nn \l_@@_item_width_viii_dim { ( \l_@@_rightmargin_viii_dim * \l_@@_tmpa_vii_int ) / \l_@@_columns_viii_int } \dim_add:Nn \l_@@_columns_sep_viii_dim { \l_@@_rightmargin_viii_dim } } } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for join item columns} % % \begin{macro}{\@@_starred_joined_item_vii:n, \@@_starred_joined_item_viii:n,} % The functions \cs{@@_starred_joined_item_vii:n} and \cs{@@_starred_joined_item_viii:n} % will set the \emph{width} of the box in which the \mymeta{content} % passed to \ics*{item}\myparg{columns} will be stored together with % the value of |\itemwidth| for the \myenv*{enumext*} environment. % \iffalse %% Set width for joined item's for |enumext*| and |keyans*| environments. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_starred_joined_item_vii:n #1 { \int_set:Nn \l_@@_joined_item_vii_int {#1} \int_compare:nNnT { \l_@@_joined_item_vii_int } > { \l_@@_columns_vii_int } { \msg_warning:nnee { enumext } { item-joined } { \int_use:N \l_@@_joined_item_vii_int } { \int_use:N \l_@@_columns_vii_int } \int_set:Nn \l_@@_joined_item_vii_int { \l_@@_columns_vii_int - \l_@@_item_column_pos_vii_int + 1 } } \int_compare:nNnT { \l_@@_joined_item_vii_int } > { \l_@@_columns_vii_int - \l_@@_item_column_pos_vii_int + 1 } { \msg_warning:nnee { enumext } { item-joined-columns } { \int_use:N \l_@@_joined_item_vii_int } { \int_eval:n { \l_@@_columns_vii_int - \l_@@_item_column_pos_vii_int + 1 } } \int_set:Nn \l_@@_joined_item_vii_int { \l_@@_columns_vii_int - \l_@@_item_column_pos_vii_int + 1 } } \int_compare:nNnTF { \l_@@_joined_item_vii_int } > { 1 } { \int_set_eq:NN \l_@@_joined_item_aux_vii_int \l_@@_joined_item_vii_int \int_decr:N \l_@@_joined_item_aux_vii_int \int_add:Nn \l_@@_item_column_pos_vii_int { \l_@@_joined_item_aux_vii_int } \int_gadd:Nn \g_@@_item_count_all_vii_int { \l_@@_joined_item_aux_vii_int } \dim_set:Nn \l_@@_joined_width_vii_dim { \l_@@_item_width_vii_dim * \l_@@_joined_item_vii_int + ( \l_@@_labelwidth_vii_dim + \l_@@_labelsep_vii_dim + \l_@@_columns_sep_vii_dim )*\l_@@_joined_item_aux_vii_int } \dim_set_eq:NN \itemwidth \l_@@_joined_width_vii_dim } { \dim_set_eq:NN \l_@@_joined_width_vii_dim \l_@@_item_width_vii_dim \dim_set_eq:NN \itemwidth \l_@@_item_width_vii_dim } } % \end{macrocode} % Same implementation for the \myenv*{keyans*} environment. % \begin{macrocode} \cs_new_protected:Npn \@@_starred_joined_item_viii:n #1 { \int_set:Nn \l_@@_joined_item_viii_int {#1} \int_compare:nNnT { \l_@@_joined_item_viii_int } > { \l_@@_columns_viii_int } { \msg_warning:nnee { enumext } { item-joined } { \int_use:N \l_@@_joined_item_viii_int } { \int_use:N \l_@@_columns_viii_int } \int_set:Nn \l_@@_joined_item_viii_int { \l_@@_columns_viii_int - \l_@@_item_column_pos_viii_int + 1 } } \int_compare:nNnT { \l_@@_joined_item_viii_int } > { \l_@@_columns_viii_int - \l_@@_item_column_pos_viii_int + 1 } { \msg_warning:nnee { enumext } { item-joined-columns } { \int_use:N \l_@@_joined_item_viii_int } { \int_eval:n { \l_@@_columns_viii_int - \l_@@_item_column_pos_viii_int + 1 } } \int_set:Nn \l_@@_joined_item_viii_int { \l_@@_columns_viii_int - \l_@@_item_column_pos_viii_int + 1 } } \int_compare:nNnTF { \l_@@_joined_item_viii_int } > { 1 } { \int_set_eq:NN \l_@@_joined_item_aux_viii_int \l_@@_joined_item_viii_int \int_decr:N \l_@@_joined_item_aux_viii_int \int_add:Nn \l_@@_item_column_pos_viii_int { \l_@@_joined_item_aux_viii_int } \int_gadd:Nn \g_@@_item_count_all_viii_int { \l_@@_joined_item_aux_viii_int } \dim_set:Nn \l_@@_joined_width_viii_dim { \l_@@_item_width_viii_dim * \l_@@_joined_item_viii_int + ( \l_@@_labelwidth_viii_dim + \l_@@_labelsep_viii_dim + \l_@@_columns_sep_viii_dim )*\l_@@_joined_item_aux_viii_int } \dim_set_eq:NN \itemwidth \l_@@_joined_width_viii_dim } { \dim_set_eq:NN \l_@@_joined_width_viii_dim \l_@@_item_width_viii_dim \dim_set_eq:NN \itemwidth \l_@@_item_width_viii_dim } } % \end{macrocode} % \end{macro} % % \subsubsection{Functions for \texttt{mini-env}, \texttt{mini-right} and \texttt{mini-right*} keys}\label{env:starred:key:mini-env} % % \begin{macro}{\@@_start_mini_vii:, \@@_stop_mini_vii:} % The implementation of the \mykey{mini-env} key support is almost % identical to the one used in the \myenv*{enumext} and \myenv*{keyans} % environments, the difference is that the \myvarenv*{__@@_mini_page} % environment on the \emph{\enquote{right side}} is executed % \emph{\enquote{after}} closing the environment, so it is necessary to % make a global copy of the variable \cs{l_@@_minipage_right_vii_dim} in % the variable \cs{g_@@_minipage_right_vii_dim}.% % \iffalse %% Start support for |mini-env| key in |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_start_mini_vii: { \dim_compare:nNnT { \l_@@_minipage_right_vii_dim } > { \c_zero_dim } { \dim_set:Nn \l_@@_minipage_left_vii_dim { \linewidth - \l_@@_minipage_right_vii_dim - \l_@@_minipage_hsep_vii_dim } \bool_set_true:N \l_@@_minipage_active_vii_bool \dim_gset_eq:NN \g_@@_minipage_right_vii_dim \l_@@_minipage_right_vii_dim \@@_mini_addvspace_vii: \nointerlineskip\noindent \@@_mini_page{ \l_@@_minipage_left_vii_dim } } } % \end{macrocode} % The function \cs{@@_stop_mini_vii:} closes the \myvarenv*{__@@_mini_page} % environment on the \emph{\enquote{left side}}, applies |\hfill| and % set the variable \cs{g_@@_minipage_active_vii_bool} to \emph{\enquote{true}} % which will be used in the function \cs{@@_after_env:nn} to execute % the \myenv{minipage} on the \emph{\enquote{right side}}. At this point % we will execute the \cs{@@_stop_list:} and \cs{@@_stop_store_level_vii:} % functions stopping the \myenv{list} environment and the level saving % mechanism for storage in \emph{sequence} of the |\anskey| command % and |anskey*| environment. This function is passed to the % \cs{@@_after_list_vii:} function in the second part of the \myenv*{enumext*} % environment definition (\S\ref{env:starred}). % \iffalse %% Stop support for |mini-env| key ans stop |list| in |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_stop_mini_vii: { \bool_if:NTF \l_@@_minipage_active_vii_bool { \@@_stop_list: \@@_stop_store_level_vii: \IfDocumentMetadataTF { \tag_resume:n {enumext*} } { } \end@@_mini_page \hfill \bool_gset_true:N \g_@@_minipage_active_vii_bool } { \@@_stop_list: \@@_stop_store_level_vii: } } % \end{macrocode} % \end{macro} % % Finally we execute the \mymarg{code} passed to the \mykey{mini-right} % or \mykey{mini-right*} keys stored in the variable \cs{g_@@_miniright_code_vii_tl} % in the \myenv{minipage} environment on the \emph{\enquote{right % side}}. For compatibility with the \mypkg{caption} package and possibly % other \mymarg{code} passed to this key, we will pass it to a box and % then print it. % \iffalse %% Exec |mini-right|, |mini-right*| keys in |enumext*| environment. % \fi % \begin{macrocode} \@@_after_env:nn {enumext*} { \bool_if:NT \g_@@_minipage_active_vii_bool { \@@_minipage:w [ t ] { \g_@@_minipage_right_vii_dim } \legacy_if_gset_false:n { @minipage } \skip_vertical:N \c_zero_skip \par\addvspace { \g_@@_minipage_right_skip } \bool_if:NF \g_@@_minipage_center_vii_bool { \tl_put_left:Nn \g_@@_miniright_code_vii_tl { \centering } } \vbox_set_top:Nn \l_@@_miniright_code_vii_box { \tl_use:N \g_@@_miniright_code_vii_tl } \box_use_drop:N \l_@@_miniright_code_vii_box \skip_vertical:N \c_zero_skip \@@_endminipage: \par\addvspace{ \g_@@_minipage_after_skip } } \bool_gset_false:N \g_@@_minipage_active_vii_bool \bool_gset_true:N \g_@@_minipage_center_vii_bool \tl_gclear:N \g_@@_miniright_code_vii_tl \dim_gzero:N \g_@@_minipage_right_vii_dim \bool_gset_false:N \g_@@_starred_bool } % \end{macrocode} % % \begin{macro}{\@@_start_mini_viii:,\@@_stop_mini_viii:} % The implementation of the \mykey{mini-env}, \mykey{mini-right} and % \mykey{mini-right*} keys is identical to the one used in the % \myenv*{enumext*} environment. % \iffalse %% Support for |mini-env|, |mini-right| and |mini-right*| key in |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_start_mini_viii: { \dim_compare:nNnT { \l_@@_minipage_right_viii_dim } > { \c_zero_dim } { \dim_set:Nn \l_@@_minipage_left_viii_dim { \linewidth - \l_@@_minipage_right_viii_dim - \l_@@_minipage_hsep_viii_dim } \bool_set_true:N \l_@@_minipage_active_viii_bool \dim_gset_eq:NN \g_@@_minipage_right_viii_dim \l_@@_minipage_right_viii_dim \@@_mini_addvspace_viii: \nointerlineskip\noindent \@@_mini_page{ \l_@@_minipage_left_viii_dim } } } \cs_new_protected:Nn \@@_stop_mini_viii: { \bool_if:NTF \l_@@_minipage_active_viii_bool { \@@_stop_list: \IfDocumentMetadataTF { \tag_resume:n {keyans*} } { } \end@@_mini_page \hfill \bool_gset_true:N \g_@@_minipage_active_viii_bool } { \@@_stop_list: } } \@@_after_env:nn {keyans*} { \bool_if:NT \g_@@_minipage_active_viii_bool { \@@_mini_page{ \g_@@_minipage_right_viii_dim } \par\addvspace { \g_@@_minipage_right_skip } \bool_if:NF \g_@@_minipage_center_viii_bool { \tl_put_left:Nn \g_@@_miniright_code_viii_tl { \centering } } \vbox_set_top:Nn \l_@@_miniright_code_viii_box { \tl_use:N \g_@@_miniright_code_viii_tl } \box_use_drop:N \l_@@_miniright_code_viii_box \end@@_mini_page \par\addvspace{ \g_@@_minipage_after_skip } } \bool_gset_false:N \g_@@_minipage_active_viii_bool \bool_gset_true:N \g_@@_minipage_center_viii_bool \tl_gclear:N \g_@@_miniright_code_viii_tl \dim_gzero:N \g_@@_minipage_right_viii_dim } % \end{macrocode} % \end{macro} % % \subsection{The environment \env{enumext*}}\label{env:starred} % % \begin{macro}{enumext*} % First we will generate the environment and we will give a % temporary definition to \cs{@@_stop_item_tmp_vii:} equal to % \cs{@@_first_item_tmp_vii:} and next to |\item| equal to \cs{@@_start_item_tmp_vii:} % which we will redefine later. Unlike the implementation used by % the \mypkg{shortlst} package, we will not set the values ​​of % |\rightskip| and |\@rightskip| equal to |\@flushglue| whose value is % \mydim{0.0pt plus 1.0 fil}, in the tests I have performed this fails in % some circumstances and different results are obtained when using % \hologo{pdfTeX} and \hologo{LuaTeX}. % \iffalse %% Define |enumext*| % \fi % \begin{macrocode} \NewDocumentEnvironment{enumext*}{ o } { \@@_safe_exec_vii: \@@_parse_keys_vii:n {#1} \@@_before_list_vii: \@@_start_store_level_vii: \@@_start_list:nn { } { \@@_list_arg_two_vii: \@@_before_keys_exec_vii: } \IfDocumentMetadataTF { \tag_suspend:n {enumext*} } { } \@@_starred_columns_set_vii: \item[] \scan_stop: \cs_set_eq:NN \@@_stop_item_tmp_vii: \@@_first_item_tmp_vii: \cs_set_eq:NN \item \@@_start_item_tmp_vii: \ignorespaces } { \IfDocumentMetadataTF { \tag_struct_end:n {tag=text-unit} } { } \@@_stop_item_tmp_vii: \@@_remove_extra_parsep_vii: \@@_after_list_vii: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_safe_exec_vii:}\label{fun:starred:safe-exe} % We will first call the function \cs{@@_is_not_nested:} which sets % \cs{g_@@_starred_bool} to true if we are NOT nested within \myenv*{enumext}, % then call the function \cs{@@_internal_mini_page:} to create the % environment \myvarenv*{__@@_mini_page}, we will increment % \cs{l_@@_level_h_int} to restrict nesting of the environment, set % \cs{l_@@_starred_bool} to true and finally call the function % \cs{@@_is_on_first_level:} which sets \cs{l_@@_starred_first_bool} to % true if we are not nested, allowing the \emph{\enquote{storage system}} % to be used. % \iffalse %% Safe exec for |enumext*| environment (set vars for storage system). % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_safe_exec_vii: { \@@_is_not_nested: \@@_internal_mini_page: \int_incr:N \l_@@_level_h_int \int_compare:nNnT { \l_@@_level_h_int } > { 1 } { \msg_error:nn { enumext } { nested } } \int_compare:nNnT { \l_@@_keyans_level_h_int } = { 1 } { \msg_error:nnn { enumext } { nested-horizontal } { keyans*} } \bool_set_true:N \l_@@_starred_bool \bool_set_false:N \l_@@_standar_bool \@@_is_on_first_level: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_keys_vii:n} % First we will clear the variable \cs{l_@@_series_str} used by the key % \mykey{series}, process the environment \myoarg{key \textnormal{\textcolor{gray}{=}} val} % and execute the function \cs{@@_parse_series:n} and used by the key % \mykey{series}, then we execute the function \cs{@@_store_active_keys_vii:n} % and reprocess the \mymeta{keys} to pass them to the storage \emph{sequence} % if the key \mykey{save-key} is not active. %^^A and finally we call the function %^^A \cs{@@_nested_base_line_fix:} used by the key \mykey{base-fix}. % \iffalse %% Parse |key=val| and store keys for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_parse_keys_vii:n #1 { \tl_if_novalue:nF {#1} { \str_clear:N \l_@@_series_str \keys_set:nn { enumext / enumext* } {#1} \@@_parse_series:n {#1} \@@_store_active_keys_vii:n {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_before_list_vii:} % The function \cs{@@_before_list_vii:} first calls the function % \cs{@@_vspace_above_vii:} used by the keys \mykey{above} and % \mykey{above*}, then calls the function \cs{@@_check_ans_active:} for % the check answer mechanism and finally calls the functions % \cs{@@_before_args_exec:} and \cs{@@_start_mini_vii:} used by the % keys \mykey{before*}, \mykey{mini-env}, \mykey{mini-right} and % \mykey{mini-right*}. % \begin{macrocode} \cs_new_protected:Nn \@@_before_list_vii: { \@@_vspace_above_vii: \@@_check_ans_active: \@@_before_args_exec_vii: \@@_start_mini_vii: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_after_list_vii:} % The function \cs{@@_after_list_vii:} first calls the function % \cs{@@_stop_mini_vii:} which internally calls \cs{@@_stop_list:} and % \cs{@@_stop_store_level_vii:} (\S\ref{env:starred:key:mini-env}) used % by the keys \mykey{mini-env}, \mykey{mini-right} and \mykey{mini-right*}, % then to the functions \cs{@@_after_stop_list_vii:} used by the key % \mykey{after}, \cs{@@_check_ans_key_hook:} used by the key \mykey{check-ans}, % \cs{@@_vspace_below_vii:} used by the keys \mykey{below} and % \mykey{below*}. Finally set \cs{l_@@_starred_bool} to false and call % the \cs{@@_resume_save_counter:} function used by the \mykey{series}, % \mykey{resume} and \mykey{resume*} keys. % \begin{macrocode} \cs_new_protected:Nn \@@_after_list_vii: { \@@_stop_mini_vii: \@@_after_stop_list_vii: \@@_check_ans_key_hook: \@@_vspace_below_vii: \bool_set_false:N \l_@@_starred_bool \@@_resume_save_counter: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_start_store_level_vii:, \@@_stop_store_level_vii:} % The \cs{@@_start_store_level_vii:} and \cs{@@_stop_store_level_vii:} % functions activate the \emph{\enquote{storing structure}} mechanism % in \emph{sequence} for \ics*{anskey} command and \myenv*{anskey*} % environment if \myenv*{enumext*} are nested in \myenv*{enumext}. % \begin{macrocode} \cs_new_protected:Nn \@@_start_store_level_vii: { \bool_if:NT \l_@@_store_active_bool { \int_compare:nNnT { \l_@@_level_int } > { 0 } { \@@_store_level_open_vii: } } } \cs_new_protected:Nn \@@_stop_store_level_vii: { \bool_if:NT \l_@@_store_active_bool { \int_compare:nNnT { \l_@@_level_int } > { 0 } { \@@_store_level_close_vii: } } } % \end{macrocode} % \end{macro} % % \subsubsection{The command \cs{item} in \env{enumext*}}\label{cmd:item-boxed-vii} % % \begin{macro}{\@@_first_item_tmp_vii:} % % The \cs{@@_first_item_tmp_vii:} function will remove horizontal space % equal to |\labelwidth| plus |\labelsep| to the left of the \emph{\enquote{first}} % |\item| in the environment at the point of execution of this function, % where it is equal to the \cs{@@_stop_item_tmp_vii:} function inside the % environment body definition. % \iffalse %% Remove |\labelwidth+\labelsep| on left in first |\item| for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_first_item_tmp_vii: { \skip_horizontal:n { -\l_@@_labelwidth_vii_dim - \l_@@_labelsep_vii_dim } \ignorespaces } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_start_item_tmp_vii:, \@@_item_peek_args_vii:, % \@@_joined_item_vii:w, \@@_standar_item_vii:w, % \@@_starred_item_vii:w, \@@_starred_item_vii_aux_i:w, % \@@_starred_item_vii_aux_ii:w, \@@_starred_item_vii_aux_iii:w,} % First we will call the function \cs{@@_stop_item_tmp_vii:} that we % will redefine later, we will increment the value of % \cs{l_@@_item_column_pos_vii_int} that will count the item's by rows and % the value of \cs{g_@@_item_count_all_vii_int} that will count the % total of item's in the environment. After that we will call the % function \cs{@@_item_peek_args_vii:} that will handle the % arguments passed to \ics*{item}. % \iffalse %% Start boxed item's for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_start_item_tmp_vii: { \@@_stop_item_tmp_vii: \int_incr:N \l_@@_item_column_pos_vii_int \int_gincr:N \g_@@_item_count_all_vii_int \@@_item_peek_args_vii: } % \end{macrocode} % The function \cs{@@_item_peek_args_vii:} will handle the \ics*{item}\myparg{number}. % Look for the argument \enquote{\textcolor{MediumOrchid}{\ttfamily (}}, % if it is present we will call the function \cs{@@_joined_item_vii:w} \myparg{number}, % which is in charge of joining the item's in the same row, in case they % are not present we will set the default value \textcolor{gray}{\ttfamily(\mydim{1})}. % \iffalse %% Peek argument for \item()*[][] for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_item_peek_args_vii: { \peek_meaning:NTF ( { \@@_joined_item_vii:w } { \@@_joined_item_vii:w (1) } } % \end{macrocode} % The function \cs{@@_joined_item_vii:w} will first call the % function \cs{@@_starred_joined_item_vii:n} in charge of setting the % \emph{width} of the box that will store the content passed to \ics*{item}. Then we % will look for the argument \enquote{\textcolor{MediumOrchid}{\ttfamily *}}, if it is present we will call the % function \cs{@@_starred_item_vii:w} otherwise we will call the % function \cs{@@_standar_item_vii:w}. % \iffalse %% Joined item's for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_joined_item_vii:w (#1) { \@@_starred_joined_item_vii:n {#1} \peek_meaning_remove:NTF * { \@@_starred_item_vii:w } { \@@_standar_item_vii:w } } % \end{macrocode} % The function \cs{@@_standar_item_vii:w} will first look for the % argument “|[|”, if present it will set the state of the variable % \cs{l_@@_wrap_label_opt_vii_bool} equal to the state of the variable % \cs{l_@@_wrap_label_opt_vii_bool} handled by the key % \mykey{wrap-label*} and finally execute the \emph{non-enumerated} % version \ics*{item}\myoarg{custom} by means of the function % \cs{@@_start_item_vii:w}, otherwise we will set the value of the % variable \cs{l_@@_wrap_label_vii_bool} handled by the % \mykey{wrap-label} key to true and set the switch |\if@noitemarg| to % true to execute the enumerated version of \ics*{item} by means of the % function \cs{@@_start_item_vii:w} |[| \myvarenv{l__@@_label_vii_tl} |]|. % \iffalse %% Set \item[opt] for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_standar_item_vii:w { \bool_set_false:N \l_@@_item_starred_vii_bool \peek_meaning:NTF [ { \bool_set_eq:NN \l_@@_wrap_label_vii_bool \l_@@_wrap_label_opt_vii_bool \@@_start_item_vii:w } { \bool_set_true:N \l_@@_wrap_label_vii_bool \legacy_if_set_true:n { @noitemarg } \@@_start_item_vii:w [ \l_@@_label_vii_tl ] \ignorespaces } } % \end{macrocode} % The function \cs{@@_starred_item_vii:w} together with the specified % auxiliary functions |aux_i:w|, |aux_ii:w|, and |aux_iii:w| execute \ics*{item*}, % \ics*{item*}\myoarg{symbol} and \ics*{item*}\myoarg{symbol}\myoarg{offset}. % \iffalse %% Set \item*[sym][sep] for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_starred_item_vii:w { \bool_set_true:N \l_@@_item_starred_vii_bool \bool_set_true:N \l_@@_wrap_label_vii_bool \peek_meaning:NTF [ { \@@_starred_item_vii_aux_i:w } { \@@_starred_item_vii_aux_ii:w } } \cs_new_protected:Npn \@@_starred_item_vii_aux_i:w [#1] { \tl_gset:Nn \g_@@_item_symbol_aux_vii_tl {#1} \@@_starred_item_vii_aux_ii:w } \cs_new_protected:Npn \@@_starred_item_vii_aux_ii:w { \peek_meaning:NTF [ { \@@_starred_item_vii_aux_iii:w } { \dim_set_eq:NN \l_@@_item_symbol_sep_vii_dim \l_@@_labelsep_vii_dim \legacy_if_set_true:n { @noitemarg } \@@_start_item_vii:w [ \l_@@_label_vii_tl ] \ignorespaces } } \cs_new_protected:Npn \@@_starred_item_vii_aux_iii:w [#1] { \dim_set:Nn \l_@@_item_symbol_sep_vii_dim {#1} \legacy_if_set_true:n { @noitemarg } \@@_start_item_vii:w [ \l_@@_label_vii_tl ] \ignorespaces } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_fake_make_label_vii:n} % The \cs{@@_fake_make_label_vii:n} function will be in charge of % handling our definition of |\item|. First we increment the counter % \icounter{enumXvii} for the enumerated items and activate support for % the \emph{check answers} mechanism, followed by support for % \ics*{item*}\myoarg{symbol}\myoarg{offset} if present, then the % \mykey{wrap-label} and \mykey{wrap-label*} keys which we execute using % |\makebox| whose width will be given by the \mykey{labelwidth} key and % position by the \mykey{align} key, inside the argument of this we will % execute the \mykey{font} key together with the function defined by the % \mykey{wrap-label} or \mykey{wrap-label*} keys. Finally we execute the % \mykey{labelsep} key applying a |\skip_horizontal:N| and |\ignorespaces|. % % \smallskip % % \begin{important} % For compatibility with \emph{tagged} \texttt{PDF} and \mypkg{hyperref} % when an environment \myenv*{enumext} is nested in \myenv*{enumext*} % and the key \mykey{save-ans} is not active need setting the |\if@hyper@item| % switch to \emph{\enquote{true}}. The explanation for this is given % by the master Heiko Oberdiek on \href{https://tex.stackexchange.com/a/404911}{\textbackslash % refstepcounter\{enumi\} twice (or more) creates destination with the % same identifier}. % This patch is only needed if you are running |pdflatex| and not if % you are running |lualatex| % \end{important} % % \iffalse %% Fake \makelabel definition for |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_fake_make_label_vii:n #1 { \legacy_if:nT { @noitemarg } { \legacy_if_set_false:n { @noitemarg } \legacy_if:nT { @nmbrlist } { \IfDocumentMetadataTF { \bool_if:NT \l_@@_hyperref_bool { \legacy_if_set_true:n { @hyper@item } } } { } \refstepcounter{enumXvii} \bool_if:NT \l_@@_check_answers_bool { \int_gincr:N \g_@@_item_number_int \bool_set_true:N \l_@@_item_number_bool } } } \bool_if:NT \l_@@_item_starred_vii_bool { \tl_if_blank:VT \g_@@_item_symbol_aux_vii_tl { \tl_gset_eq:NN \g_@@_item_symbol_aux_vii_tl \l_@@_item_symbol_vii_tl } \mode_leave_vertical: \skip_horizontal:n { -\l_@@_item_symbol_sep_vii_dim } \hbox_overlap_left:n { \g_@@_item_symbol_aux_vii_tl } \skip_horizontal:N \l_@@_item_symbol_sep_vii_dim \tl_gclear:N \g_@@_item_symbol_aux_vii_tl } \makebox[ \l_@@_labelwidth_vii_dim ][ \l_@@_align_label_vii_str ] { \tl_use:N \l_@@_label_font_style_vii_tl \bool_if:NTF \l_@@_wrap_label_vii_bool { \@@_wrapper_label_vii:n {#1} } { #1 } } \skip_horizontal:N \l_@@_labelsep_vii_dim \ignorespaces } % \end{macrocode} % \end{macro} % % \subsubsection{Real definition of \cs{item} in \env{enumext*}} % % The functions \cs{@@_start_item_vii:w} and \cs{@@_stop_item_vii:} executing % the true definition of \ics*{item} inside the \myenv*{enumext*} environment, unlike % the implementation in \mypkg{shortlst} we will NOT use an extra group % and the plain form of the \myenv{lrbox} environment. % % \begin{macro}{\@@_start_item_vii:w, \@@_stop_item_vii:} % The first thing we will do is set the value of \cs{@@_stop_item_tmp_vii:} equal to % \cs{@@_stop_item_vii:} which we will define later, after that we will % start capturing |\item| and \emph{\enquote{item content}} in a \emph{horizontal box} % where the width will be |\itemwidth| plus |\labelwidth| plus |\labelsep|. % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_start_item_vii:w [#1] { \cs_set_eq:NN \@@_stop_item_tmp_vii: \@@_stop_item_vii: \hbox_set_to_wd:Nnw \l_@@_item_text_vii_box { \l_@@_joined_width_vii_dim + \l_@@_labelwidth_vii_dim + \l_@@_labelsep_vii_dim } % \end{macrocode} % Redefine the |\footnote| command. % \begin{macrocode} \@@_renew_footnote_starred: % \end{macrocode} % Now we insert our \emph{sockets} for \emph{tagging} \texttt{PDF} % support and run |\item|. % \begin{macrocode} \@@_start_list_tag:n {enumext*} \@@_fake_make_label_vii:n {#1} \@@_stop_start_list_tag: % \end{macrocode} % Finally we open the \myenv{minipage} environment, capture the % \emph{\enquote{item content}}, make |\parindent| take the value of the % key \mykey{listparindent} and |\parskip| take the value of the key % \mykey{parsep}, then execute the keys \mykey{itemindent} and % \mykey{first}. % % \smallskip % % \begin{important}* % Here the use of |\unskip| and |\skip_horizontal:n| with the value of % \mykey{listparindent} is necessary, otherwise an unwanted space is % created when using |\item|\myoarg{opt} and the value passed to the key % \mykey{itemindent} is incremented. % \end{important} % % \smallskip % % \begin{macrocode} \@@_minipage:w [ t ]{ \l_@@_joined_width_vii_dim } \dim_set_eq:NN \parindent \l_@@_listparindent_vii_dim \skip_set_eq:NN \parskip \l_@@_parsep_vii_skip \@@_unskip_unkern: \@@_unskip_unkern: \skip_horizontal:n { -\l_@@_listparindent_vii_dim } \ignorespaces \tl_use:N \l_@@_fake_item_indent_vii_tl \tl_use:N \l_@@_after_list_args_vii_tl } % \end{macrocode} % The \cs{@@_stop_item_vii:} function will finish the fetching |\item| % and \emph{\enquote{item content}} by closing the \myenv{minipage} % environment, the \emph{sockets} for \emph{tagging} \texttt{PDF} and the % \emph{horizontal box}. % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_stop_item_vii: { \@@_endminipage: \@@_stop_list_tag:n {enumext*} \hbox_set_end: % \end{macrocode} % Here we will reduce the \emph{warnings} a bit by setting the value % of |\hbadness| to \mydim{10000}, print |\item| and \emph{\enquote{item content}} % from the \emph{horizontal box},. % \begin{macrocode} \int_set:Nn \hbadness { 10000 } \box_use_drop:N \l_@@_item_text_vii_box % \end{macrocode} % Finally apply the \emph{vertical space} between rows set by \mykey{itemsep} % key passed to |\parsep| using |\par\noindent| and \emph{horizontal space} % between columns set by \mykey{columns-sep} key using |\skip_horizontal:N|. % \begin{macrocode} \int_compare:nNnTF { \l_@@_item_column_pos_vii_int } = { \l_@@_columns_vii_int } { \par\noindent \int_zero:N \l_@@_item_column_pos_vii_int } { \skip_horizontal:N \l_@@_columns_sep_vii_dim } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_remove_extra_parsep_vii:} % Remove the extra \emph{vertical space} equal to |\parsep=\itemsep| when the % total number of |\item| is divisible by the number of |\item| in the last % row of the environment. Here the use of |\unskip| or |\removelastskip| % fails and does not obtain the expected result, using |\vspace| is % the option and in this case, we can use a simplified version since % we are always in \mymeta{vertical mode}. % \iffalse %% Remove extra \parsep in |enumext*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_remove_extra_parsep_vii: { \int_compare:nNnT { \int_mod:nn { \g_@@_item_count_all_vii_int } { \l_@@_columns_vii_int } } = { 0 } { \para_end: \skip_vertical:n { -\l_@@_itemsep_vii_skip } \skip_vertical:N \c_zero_skip \int_gzero:N \g_@@_item_count_all_vii_int } } % \end{macrocode} % \end{macro} % % \smallskip % % As we don't want our check to be executed \mykey{check-ans} by levels % but on the complete list, we will take it out of the \myenv*{enumext*} % environment using the \emph{\enquote{hook}} function \cs{@@_after_env:nn}. % \iffalse %% Execute |check-ans| key out of |enumext*| environment. % \fi % \begin{macrocode} \@@_after_env:nn {enumext*} { \@@_execute_after_env: } % \end{macrocode} % % \subsection{The environment \env{keyans*}}\label{env:keyans-starred} % % \begin{macro}{keyans*} % The implementation of \myenv*{keyans*} environment is the % similar as that used by the \myenv*{enumext*} environment except for the % \cs{@@_check_starred_cmd:n} function added in the second part. % \iffalse %% Define |keyans*| environment. % \fi % \begin{macrocode} \NewDocumentEnvironment{keyans*}{ o } { \@@_safe_exec_viii: \@@_parse_keys_viii:n {#1} \@@_before_list_viii: \@@_start_list:nn { } { \@@_list_arg_two_viii: \@@_before_keys_exec_viii: } \IfDocumentMetadataTF { \tag_suspend:n {keyans*} } { } \@@_starred_columns_set_viii: \item[] \scan_stop: \cs_set_eq:NN \@@_stop_item_tmp_viii: \@@_first_item_tmp_viii: \cs_set_eq:NN \item \@@_start_item_tmp_viii: \ignorespaces } { \IfDocumentMetadataTF { \tag_struct_end:n {tag=text-unit} } { } \@@_stop_item_tmp_viii: \@@_remove_extra_parsep_viii: \@@_check_starred_cmd:n { item } \@@_after_list_viii: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_safe_exec_viii:} % The \cs{@@_safe_exec_viii:} function will first check if the % \mykey{save-ans} key is active and only when this is true the % environment will be available, it will increment the value of % \cs{l_@@_keyans_level_h_int} and return an error message when we are % nesting the environment, then it will call the % \cs{@@_keyans_name_and_start:} function in charge of saving the name of % the environment and the line it is running on, then it will check if we % are trying to nest \myenv*{keyans*} in \myenv*{enumext*} returning an % error and we will set \cs{l_@@_starred_bool} to true, finally we will % check if we are within the appropriate level within the % \myenv*{enumext} environment. % \iffalse %% Test deep-level for |keyans*| environment and set bool vars. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_safe_exec_viii: { \bool_if:NF \l_@@_store_active_bool { \msg_error:nnnn { enumext } { wrong-place }{ keyans* }{ save-ans } } \int_incr:N \l_@@_keyans_level_h_int \int_compare:nNnT { \l_@@_keyans_level_h_int } > { 1 } { \msg_error:nn { enumext } { nested } } \@@_keyans_name_and_start: \bool_if:NT \l_@@_starred_bool { \msg_error:nnn { enumext } { nested-horizontal } { enumext* } } \bool_set_true:N \l_@@_starred_bool % Set false for interfering with enumext nested in keyans* (yes, its possible and crayze) \bool_set_false:N \l_@@_store_active_bool \int_compare:nNnT { \l_@@_level_int } > { 1 } { \msg_error:nn { enumext } { keyans-wrong-level } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_parse_keys_viii:n} % Parse \myoarg{key \textnormal{\textcolor{gray}{=}} val} % for \myenv*{keyans*}. % \iffalse %% Parse |key=val| and store keys for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_parse_keys_viii:n #1 { \tl_if_novalue:nF {#1} { \keys_set:nn { enumext / keyans* } {#1} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_before_list_viii:} % The function \cs{@@_before_list_viii:} will add the vertical % spacing on the environment if the \mykey{above} key is active next to % the \mymarg{code} defined by the \mykey{before*} key if % it is active, the call the function \cs{@@_start_mini_viii:} handle by % \mykey{mini-env}. % \begin{macrocode} \cs_new_protected:Nn \@@_before_list_viii: { \@@_vspace_above_viii: \@@_before_args_exec_viii: \@@_start_mini_viii: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_after_list_viii:} % The function \cs{@@_after_list_viii:} first call the function \cs{@@_stop_mini_viii:}, % then apply the \mymarg{code} handled by the \mykey{after} key % together with the \emph{vertical space} handled by the \mykey{below} key if % they are present. % \begin{macrocode} \cs_new_protected:Nn \@@_after_list_viii: { \@@_stop_mini_viii: \@@_after_stop_list_viii: \@@_vspace_below_viii: } % \end{macrocode} % \end{macro} % % \subsubsection{The command \cs{item} in \env{keyans*}}\label{cmd:item-boxed-viii} % % The idea here is to make the |\item| command behave in the same way as % in the \myenv*{keyans} environment with the difference of the \emph{optional argument} % \myparg{number} which works in the same way as in the \myenv*{enumext*} % environment. % % In simple terms we want to store the \mymeta{label} next to the \myoarg{content} if it is present % in the \emph{sequence} and \emph{prop list} defined by \mykey{save-ans} key for % |\item*|, |\item*|\myoarg{content}, |\item|\myparg{number}|*| and % |\item|\myparg{number}|*|\myoarg{content} commands. % % \begin{macro}{\@@_first_item_tmp_viii:} % The \cs{@@_first_item_tmp_viii:} function will remove horizontal space % equal to |\labelwidth| plus |\labelsep| to the left of the \emph{\enquote{first}} % |\item| in the environment at the point of execution of this function, % where it is equal to the \cs{@@_stop_item_tmp_viii:} function inside the % environment body definition. % \iffalse %% Remove |\labelwidth+\labelsep| on left in first |\item| for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_first_item_tmp_viii: { \skip_horizontal:n { -\l_@@_labelwidth_viii_dim - \l_@@_labelsep_viii_dim } \ignorespaces } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_start_item_tmp_viii:, \@@_item_peek_args_viii:, % \@@_joined_item_viii:w, \@@_standar_item_viii:w} % First we will call the function \cs{@@_stop_item_tmp_viii:} that we % will redefine later, we will increment the value of % \cs{l_@@_item_column_pos_viii_int} that will count the item's by rows and % the value of \cs{g_@@_item_count_all_viii_int} that will count the % total of item's in the environment. After that we will call the % function \cs{@@_item_peek_args_viii:} that will handle the % arguments passed to \ics*{item}. % \iffalse %% Start boxed item's for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Nn \@@_start_item_tmp_viii: { \@@_stop_item_tmp_viii: \int_incr:N \l_@@_item_column_pos_viii_int \int_gincr:N \g_@@_item_count_all_viii_int \@@_item_peek_args_viii: } % \end{macrocode} % The function \cs{@@_item_peek_args_viii:} will handle the \ics*{item}\myparg{number}. % Look for the argument \enquote{\textcolor{MediumOrchid}{\ttfamily (}}, if it is % present we will call the function \cs{@@_joined_item_viii:w} \myparg{number}, which is in charge of joining the item's % in the same row, in case they are not present we will set the default % value \textcolor{gray}{\ttfamily(\mydim{1})}. % \iffalse %% Peek argument for \item(number)*[opt] for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_item_peek_args_viii: { \peek_meaning:NTF ( { \@@_joined_item_viii:w } { \@@_joined_item_viii:w (1) } } % \end{macrocode} % The function \cs{@@_joined_item_viii:w} will first call the % function \cs{@@_starred_joined_item_viii:n} in charge of setting the % \emph{width} of the box that will store the content passed to \ics*{item}. Then we % will look for the argument \enquote{\textcolor{MediumOrchid}{\ttfamily *}}, if it is present we will call the % function \cs{@@_starred_item_viii:w} otherwise we will call the % function \cs{@@_standar_item_viii:w}. % \iffalse %% Joined item's for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_joined_item_viii:w (#1) { \@@_starred_joined_item_viii:n {#1} \peek_meaning_remove:NTF * { \@@_starred_item_viii:w } { \@@_standar_item_viii:w } } % \end{macrocode} % The function \cs{@@_standar_item_viii:w} will first look for the % argument “|[|”, if present it will set the state of the variable % \cs{l_@@_wrap_label_opt_viii_bool} equal to the state of the variable % \cs{l_@@_wrap_label_opt_viii_bool} handled by the key % \mykey{wrap-label*} and finally execute the \emph{non-enumerated} % version \ics*{item}\myoarg{custom} by means of the function % \cs{@@_start_item_viii:w}, otherwise we will set the value of the % variable \cs{l_@@_wrap_label_viii_bool} handled by the % \mykey{wrap-label} key to true and set the switch |\if@noitemarg| to % true to execute the enumerated version of \ics*{item} by means of the % function \cs{@@_start_item_viii:w} |[| \myvarenv{l__@@_label_viii_tl} |]|. % \iffalse %% Set standard \item[opt] for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_standar_item_viii:w { \bool_set_false:N \l_@@_item_starred_viii_bool \peek_meaning:NTF [ { \bool_set_eq:NN \l_@@_wrap_label_viii_bool \l_@@_wrap_label_opt_viii_bool \@@_start_item_viii:w } { \bool_set_true:N \l_@@_wrap_label_viii_bool \legacy_if_set_true:n { @noitemarg } \@@_start_item_viii:w [ \l_@@_label_viii_tl ] \ignorespaces } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_starred_item_viii:w, \@@_starred_item_viii_aux_i:w, % \@@_starred_item_viii_aux_ii:w, \@@_starred_item_exec:} % The function \cs{@@_starred_item_viii:w} together with the specified % auxiliary functions |aux_i:w| and |aux_ii:w| execute \ics*{item*} % and \ics*{item*}\myoarg{content}. % \iffalse %% Set \item*[content] for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_starred_item_viii:w { \bool_set_true:N \l_@@_item_starred_viii_bool \bool_set_true:N \l_@@_wrap_label_viii_bool \peek_meaning:NTF [ { \@@_starred_item_viii_aux_i:w } { \@@_starred_item_viii_aux_ii:w } } % \end{macrocode} % The function \cs{@@_starred_item_viii_aux_i:w} will save the % \emph{optional argument} to |\item*| in \cs{l_@@_store_current_opt_arg_tl} % and will save this argument along with the spacing set by the key \mykey{save-sep} in % variable \cs{l_@@_store_current_label_tl} if present, then call the % function \cs{@@_starred_item_viii_aux_ii:w}. % \begin{macrocode} \cs_new_protected:Npn \@@_starred_item_viii_aux_i:w [#1] { \tl_clear:N \l_@@_store_current_label_tl \tl_if_novalue:nF { #1 } { \tl_if_empty:NF \l_@@_store_keyans_item_opt_sep_tl { \tl_put_right:Ne \l_@@_store_current_label_tl { \l_@@_store_keyans_item_opt_sep_tl } \tl_put_right:Ne \l_@@_store_current_label_tl { #1 } } \tl_set:Ne \l_@@_store_current_opt_arg_tl { #1 } } \@@_starred_item_viii_aux_ii:w } \cs_new_protected:Npn \@@_starred_item_viii_aux_ii:w { \legacy_if_set_true:n { @noitemarg } \@@_start_item_viii:w [ \l_@@_label_viii_tl ] \ignorespaces } % \end{macrocode} % The function \cs{@@_starred_item_exec:} will be in charge of storing % the current \mymeta{label} for \ics*{item*} followed by the % \myoarg{content} for \ics*{item*}\myoarg{content} if % present in the \emph{sequence} and \emph{prop list} set by the % \mykey{save-ans} key. In this same function the keys \mykey{show-ans}, % \mykey{show-pos} and \mykey{save-ref} are implemented. % \iffalse %% Set \item*[content] for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_starred_item_exec: { \tl_put_left:Ne \l_@@_store_current_label_tl { \l_@@_label_viii_tl } \@@_store_addto_prop:V \l_@@_store_current_label_tl \@@_keyans_store_ref: \tl_put_left:Ne \l_@@_store_current_label_tl { \item } \@@_keyans_addto_seq_link: \int_gincr:N \g_@@_check_starred_cmd_int \bool_if:NT \l_@@_show_answer_bool { \@@_print_keyans_box:NN \l_@@_labelwidth_i_dim \l_@@_labelsep_i_dim } \bool_if:NT \l_@@_show_position_bool { \tl_set:Ne \l_@@_mark_answer_sym_tl { \group_begin: \exp_not:N \normalfont \exp_not:N \footnotesize [ \int_eval:n { \prop_count:c { g_@@_ \l_@@_store_name_tl _prop } } ] \group_end: } \@@_print_keyans_box:NN \l_@@_labelwidth_i_dim \l_@@_labelsep_i_dim } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_fake_make_label_viii:n} % The implementation at this is very similar to that of the % \myenv*{enumext*} environment. % \iffalse %% Define a fake |\makelabel| for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_fake_make_label_viii:n #1 { \legacy_if:nT { @noitemarg } { \legacy_if_set_false:n { @noitemarg } \legacy_if:nT { @nmbrlist } { \refstepcounter{enumXviii} } } \bool_if:NT \l_@@_item_starred_viii_bool { \@@_starred_item_exec: } \makebox[ \l_@@_labelwidth_viii_dim ][ \l_@@_align_label_viii_str ] { \tl_use:N \l_@@_label_font_style_viii_tl \bool_if:NTF \l_@@_wrap_label_viii_bool { \@@_wrapper_label_viii:n {#1} } { #1 } } \skip_horizontal:N \l_@@_labelsep_viii_dim \ignorespaces } % \end{macrocode} % \end{macro} % % \subsubsection{Real definition of \cs{item} in \env{keyans*}} % % \begin{macro}{\@@_start_item_viii:w, \@@_stop_item_viii:} % The implementation at this is very similar to that of the % \myenv*{enumext*} environment. % \iffalse %% Real |\item| definition for |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_start_item_viii:w [#1] { \cs_set_eq:NN \@@_stop_item_tmp_viii: \@@_stop_item_viii: \hbox_set_to_wd:Nnw \l_@@_item_text_viii_box { \l_@@_joined_width_viii_dim + \l_@@_labelwidth_viii_dim + \l_@@_labelsep_viii_dim } \@@_renew_footnote_starred: \@@_start_list_tag:n {keyans*} \@@_fake_make_label_viii:n {#1} \@@_stop_start_list_tag: \@@_minipage:w [ t ]{ \l_@@_joined_width_viii_dim } \dim_set_eq:NN \parindent \l_@@_listparindent_viii_dim \skip_set_eq:NN \parskip \l_@@_parsep_viii_skip \@@_unskip_unkern: \@@_unskip_unkern: \skip_horizontal:n { -\l_@@_listparindent_viii_dim } \ignorespaces \tl_use:N \l_@@_fake_item_indent_viii_tl \bool_if:NT \l_@@_item_starred_viii_bool { \@@_keyans_show_item_opt: } \tl_use:N \l_@@_after_list_args_viii_tl } \cs_new_protected_nopar:Nn \@@_stop_item_viii: { \@@_endminipage: \@@_stop_list_tag:n {keyans*} \hbox_set_end: \int_set:Nn \hbadness { 10000 } \box_use_drop:N \l_@@_item_text_viii_box \int_compare:nNnTF { \l_@@_item_column_pos_viii_int } = { \l_@@_columns_viii_int } { \par\noindent \int_zero:N \l_@@_item_column_pos_viii_int } { \skip_horizontal:N \l_@@_columns_sep_viii_dim } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_remove_extra_parsep_viii:} % The implementation at this is very similar to that of the % \myenv*{enumext*} environment. % \iffalse %% Remove extra \parsep in |keyans*| environment. % \fi % \begin{macrocode} \cs_new_protected:Nn \@@_remove_extra_parsep_viii: { \int_compare:nNnT { \int_mod:nn { \g_@@_item_count_all_viii_int } { \l_@@_columns_viii_int } } = { 0 } { \para_end: \skip_vertical:n { -\l_@@_itemsep_viii_skip } \skip_vertical:N \c_zero_skip \int_gzero:N \g_@@_item_count_all_viii_int } } % \end{macrocode} % \end{macro} % % \subsection{The command \cs{getkeyans}}\label{cmd:getkeyans} % % \begin{macro}{\getkeyans, \@@_getkeyans_aux:n, \@@_getkeyans:nn} % The \ics*{getkeyans} command takes a \emph{mandatory argument} of the % form \mymarg{store name \textcolor{red}{:} position}. % Retrieve a \emph{\enquote{single content}} stored by \ics*{anskey}, \ics*{anspic*} % and \ics*{item*} and \myenv*{anskey*} from \emph{prop list} defined by \mykey{save-ans} key. % \iffalse %% Define |\getkeyans|. % \fi % \begin{macrocode} \NewDocumentCommand \getkeyans { m } { \exp_args:Ne \@@_getkeyans_aux:n { \tl_to_str:e { \text_expand:n {#1} } } } % \end{macrocode} % The internal function \cs{@@_getkeyans_aux:n} is in charge of % \emph{splitting} the \emph{mandatory argument} using \enquote{\textcolor{red}{:}}. % If \enquote{\textcolor{red}{:}} is omitted it will return an error. % \iffalse %% Internal functions for |\getkeyans|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_getkeyans_aux:n #1 { \str_if_in:nnTF {#1} { : } { \use:e { \cs_set:Npn \exp_not:N \@@_tmp:w ##1 \c_colon_str ##2 \scan_stop: { {##1} {##2} } } \exp_after:wN \@@_getkeyans:nn \@@_tmp:w #1 \scan_stop: } { \msg_error:nnn { enumext } { missing-colon } {#1} } } % \end{macrocode} % The internal function \cs{@@_getkeyans:nn} will check for the existence % of the \emph{prop list}, if it does not exist it will return an error % message, then it will fetch the content specified by the \emph{second argument} % from \emph{prop list}. % \begin{macrocode} \cs_new_protected:Npn \@@_getkeyans:nn #1 #2 { \prop_if_exist:cTF { g_@@_#1_prop } { \prop_item:cn { g_@@_#1_prop }{#2} } { \msg_error:nnn { enumext } { undefined-storage-anskey } {#1} } } % \end{macrocode} % \end{macro} % % \subsection{The command \cs{printkeyans}}\label{cmd:printkeyans} % % The \ics*{printkeyans} command prints \emph{\enquote{all stored % content}} in the \emph{sequence} defined by the \mykey{save-ans} key. % % The first thing we will do is define a set of \mymeta{filtered keys} with % which we will control the options of the different nesting levels for % the environment \myenv*{enumext} and \myenv*{enumext*} by storing their % values ​​in the list of tokens \myvarenv{l__@@_print_keyans_X_tl}. % % \smallskip % % The variable \cs{l_@@_print_keyans_starred_tl} will have the default \mymeta{keys} % for \ics*{printkeyans*} and will be set by |\setenumext|\myoarg{print\textnormal{\textcolor{MediumOrchid}{\texttt{*}}}} % and the variable \cs{l__@@_print_keyans_vii_tl} will have the default % keys for the environment \myenv*{enumext*} nested within the \emph{sequence} % and will be set by |\setenumext|\myoarg{print \textnormal{\textcolor{gray}{,}}\textnormal{\textcolor{MediumOrchid}{\texttt{*}}}}, % the rest of the variables will be for the environment \myenv*{enumext} and will be set % by |\setenumext|\myoarg{print \textnormal{\textcolor{gray}{,}} level}. % % \iffalse %% Add keys for |\printkeyans|. % \fi % \begin{macrocode} \keys_define:nn { enumext / print } { print* .code:n = \keys_precompile:neN { enumext / enumext* } { \@@_filter_save_key:n {#1} } \l_@@_print_keyans_starred_tl, % starred cmd print* .initial:n = { nosep, label=\arabic*., columns=2, first=\small, font=\small }, print-1 .code:n = \keys_precompile:neN { enumext / level-1 } { \@@_filter_save_key:n {#1} } \l_@@_print_keyans_i_tl, print-1 .initial:n = { nosep, label=\arabic*., columns=2, first=\small, font=\small }, print-2 .code:n = \keys_precompile:neN { enumext / level-2 } { \@@_filter_save_key:n {#1} } \l_@@_print_keyans_ii_tl, print-2 .initial:n = { nosep, label=(\alph*), first=\small, font=\small }, print-3 .code:n = \keys_precompile:neN { enumext / level-3 } { \@@_filter_save_key:n {#1} } \l_@@_print_keyans_iii_tl, print-3 .initial:n = { nosep, label=\roman*., first=\small, font=\small }, print-4 .code:n = \keys_precompile:neN { enumext / level-4 } { \@@_filter_save_key:n {#1} } \l_@@_print_keyans_iv_tl, print-4 .initial:n = { nosep, label=\Alph*., first=\small, font=\small }, print-* .code:n = \keys_precompile:neN { enumext / enumext* } { \@@_filter_save_key:n {#1} } \l_@@_print_keyans_vii_tl, % starred nested print-* .initial:n = { nosep, label=\arabic*., first=\small, font=\small }, } % \end{macrocode} % % \begin{important}* % The reason for storing \mymeta{keys} in token lists using % \cs{keys_precompile:neN} is because the keys are set via % \ics*{setenumext} but are later executed by running the command % \ics*{printkeyans} and they are not handled directly by its % \emph{optional argument}, except those related to the \emph{first} % opening level. % \end{important} % % \begin{macro}{\printkeyans, \@@_printkeyans:nnn} % Create a user command to print \emph{\enquote{all stored content}} % in \emph{sequence} for \ics*{anskey}, \myenv*{anskey*}, \ics*{item*} and \ics*{anspic*}. % Within a group we will run our \emph{\enquote{precompiled keys}} and % then call the internal function \cs{@@_printkeyans:nnn}. % \iffalse %% Define |\printkeyans|. % \fi % \begin{macrocode} \NewDocumentCommand \printkeyans { s O{} m } { \group_begin: \tl_use:N \l_@@_print_keyans_i_tl \tl_use:N \l_@@_print_keyans_ii_tl \tl_use:N \l_@@_print_keyans_iii_tl \tl_use:N \l_@@_print_keyans_iv_tl \tl_use:N \l_@@_print_keyans_vii_tl \@@_printkeyans:nnn { #1 } { #2 } { #3 } \group_end: } % \end{macrocode} % The internal function \cs{@@_printkeyans:nnn} will check % for the existence of the \emph{sequence}, if it does not exist % it will return an error message, then it will check if not empty. % \iffalse %% Internal function for |\printkeyans|. % \fi % \begin{macrocode} \cs_new_protected:Npn \@@_printkeyans:nnn #1 #2 #3 { \seq_if_exist:cTF { g_@@_#3_seq } { \seq_if_empty:cF { g_@@_#3_seq } { % \end{macrocode} % If the \emph{starred argument} ‘|*|’ is present we will check that % the environment \myenv*{enumext*} is not saved in the \emph{sequence}, % then execute the variable \cs{l_@@_print_keyans_starred_tl} that % contains the default \mymeta{keys} for the environment \myenv*{enumext*}, % we set \cs{l_@@_base_line_fix_bool} and \cs{l_@@_print_keyans_star_bool} % to true for \emph{baseline correction}, open the \myenv*{enumext*} % environment passing the \emph{optional argument} and map the \emph{sequence}, % then set \cs{l_@@_base_line_fix_bool} and \cs{l_@@_print_keyans_star_bool} % to false. % \begin{macrocode} \bool_if:nTF {#1} { \seq_if_in:cnTF { g_@@_#3_seq } { \end{enumext*} } { \msg_error:nnnn { enumext } { print-starred } {#3} { enumext* } } { \tl_use:N \l_@@_print_keyans_starred_tl \bool_set_true:N \l_@@_base_line_fix_bool \bool_set_true:N \l_@@_print_keyans_star_bool \begin{enumext*}[#2] \seq_map_inline:cn { g_@@_#3_seq } { ##1 } \end{enumext*} \bool_set_false:N \l_@@_base_line_fix_bool \bool_set_false:N \l_@@_print_keyans_star_bool } } % \end{macrocode} % Otherwise it will open the environment \myenv*{enumext} passing % the \emph{optional argument} to the \emph{\enquote{first level}} % then map the \emph{sequence}. % \begin{macrocode} { \begin{enumext}[#2] \seq_map_inline:cn { g_@@_#3_seq } { ##1 } \end{enumext} } } } { \msg_error:nnn { enumext } { undefined-storage-anskey } {#3} } } % \end{macrocode} % \end{macro} % % \subsection{The command \cs{setenumext}}\label{cmd:setenumext} % % The command |\setenumext| will be in charge of managing the % \mymeta{keys} passed to all environments and to the |\printkeyans| % command. We must take precautions with the \myenv*{enumext*} % environment and \emph{\enquote{first level}} of the \myenv*{enumext} % environment so as not to capture \mymeta{keys} that complicate us. % % \begin{macro}{\@@_filter_first_level:n, \@@_filter_first_level_key:n, % \@@_filter_first_level_pair:nn,} % The function \cs{@@_filter_first_level:n} will be in charge of % filtering the \mymeta{keys} passed to the environment \myenv*{enumext*} % and \emph{\enquote{first level}} of the environment \myenv*{enumext}. % \iffalse %% Internal function for filter keys in |\setenumext| for first level. % \fi % \begin{macrocode} \cs_new:Npn \@@_filter_first_level:n #1 { \use:e { \keyval_parse:NNn \@@_filter_first_level_key:n \@@_filter_first_level_pair:nn {#1} } } % \end{macrocode} % The function \cs{@@_filter_first_level_key:n} will be responsible for % filtering the \mymeta{keys} that are passed \emph{\enquote{without value}} by % excluding the keys \mykey{resume} and \mykey{resume*}. % \begin{macrocode} \cs_new:Npn \@@_filter_first_level_key:n #1 { \str_case:nnF {#1} { { resume } {} { resume* } {} } { , { \exp_not:n {#1} } } } % \end{macrocode} % The function \cs{@@_filter_first_level_pair:nn} will be responsible for % filtering the \mymeta{keys} that are passed \emph{\enquote{with value}} by % excluding the \mykey{series}, \mykey{resume} and \mykey{save-ans} keys. % \begin{macrocode} \cs_new:Npn \@@_filter_first_level_pair:nn #1#2 { \str_case:nnF {#1} { { series } {} { resume } {} { save-ans } {} } { , { \exp_not:n {#1} } = { \exp_not:n {#2} } } } % \end{macrocode} % \end{macro} % % Now define a \emph{\enquote{meta families}} of \mymeta{keys} % to access from \ics*{setenumext}. % % \iffalse %% Add keys for |\setenumext|. % \fi % \begin{macrocode} \keys_define:nn { enumext / meta-families } { enumext-1 .code:n = { \keys_set:ne { enumext / level-1 } { \@@_filter_first_level:n {#1} } } , enumext-2 .code:n = { \keys_set:nn { enumext / level-2 } {#1} } , enumext-3 .code:n = { \keys_set:nn { enumext / level-3 } {#1} } , enumext-4 .code:n = { \keys_set:nn { enumext / level-4 } {#1} } , keyans .code:n = { \keys_set:nn { enumext / keyans } {#1} } , enumext* .code:n = { \keys_set:ne { enumext / enumext* } { \@@_filter_first_level:n {#1} } } , keyans* .code:n = { \keys_set:nn { enumext / keyans* } {#1} } , print* .code:n = { \keys_set:nn { enumext / print } { print* = {#1} } } , print-1 .code:n = { \keys_set:nn { enumext / print } { print-1 = {#1} } } , print-2 .code:n = { \keys_set:nn { enumext / print } { print-2 = {#1} } } , print-3 .code:n = { \keys_set:nn { enumext / print } { print-3 = {#1} } } , print-4 .code:n = { \keys_set:nn { enumext / print } { print-4 = {#1} } } , print-* .code:n = { \keys_set:nn { enumext / print } { print-* = {#1} } } , unknown .code:n = { \msg_error:nn { enumext } { unknown-key-family } } , } % \end{macrocode} % We store them in the constant sequence \cs{c_@@_all_families_seq} % separated by commas. % \begin{macrocode} \seq_const_from_clist:Nn \c_@@_all_families_seq { enumext-1, enumext-2, enumext-3, enumext-4, keyans, enumext*, keyans*, print-1, print-2, print-3, print-4, print-*, print*, } % \end{macrocode} % % \begin{macro}{\setenumext, \@@_set_parse:n, \@@_set_error:nn,} % Now we define the user command \ics*{setenumext}. % \iffalse %% Define |\setenumext|. % \fi % \begin{macrocode} \NewDocumentCommand \setenumext { O{enumext,1} +m } { \seq_clear:N \l_@@_setkey_tmpa_seq \seq_set_from_clist:Nn \l_@@_setkey_tmpb_seq {#1} \int_set:Nn \l_@@_setkey_tmpa_int { \seq_count:N \l_@@_setkey_tmpb_seq } \int_compare:nNnTF { \l_@@_setkey_tmpa_int } > { 1 } { \seq_pop_left:NN \l_@@_setkey_tmpb_seq \l_@@_setkey_tmpa_tl \seq_map_function:NN \l_@@_setkey_tmpb_seq \@@_set_parse:n \seq_set_map_e:NNn \l_@@_setkey_tmpa_seq \l_@@_setkey_tmpa_seq { \tl_use:N \l_@@_setkey_tmpa_tl - ##1 } } { \seq_put_right:Ne \l_@@_setkey_tmpa_seq { \tl_trim_spaces:n {#1} } } \seq_if_empty:NTF \l_@@_setkey_tmpa_seq { \seq_map_inline:Nn \c_@@_all_families_seq } { \seq_map_inline:Nn \l_@@_setkey_tmpa_seq } { \keys_set:nn { enumext / meta-families } { ##1 = {#2} } } } % \end{macrocode} % Internal functions used by the \ics*{setenumext} command. % \begin{macrocode} \cs_new_protected:Npn \@@_set_parse:n #1 { \tl_set:Ne \l_@@_setkey_tmpb_tl { \tl_trim_spaces:n {#1} } \clist_map_inline:nn { 0, 1, 2, 3, 4, * } % <- max level { \tl_remove_all:Nn \l_@@_setkey_tmpb_tl {##1} } \tl_if_empty:NTF \l_@@_setkey_tmpb_tl { \seq_put_right:Ne \l_@@_setkey_tmpa_seq { \tl_trim_spaces:n {#1} } } { \@@_set_error:nn {#1} { } } } \cs_new_protected:Npn \@@_set_error:nn #1 #2 { \msg_error:nnn { enumext } { invalid-key } {#1} {#2} } % \end{macrocode} % \end{macro} % % \subsection{The command \cs{setenumextmeta}}\label{cmd:setenumextmeta} % % The command \ics*{setenumextmeta} will be responsible for adding new % \emph{\enquote{meta-keys}} for the \myenv*{enumext} and \myenv*{enumext*} environments. % The implementation code was given by Jonathan P. Spratte \texttt{(@Skillmon)} % answer in \href{https://tex.stackexchange.com/a/721079}{Add \texttt{.meta} key to existing keys (l3keys)}. % % \begin{macro}{\setenumextmeta, \c_@@_meta_paths_prop, % \@@_add_meta_key:nnn, \@@_def_meta_key:nnn, % \@@_def_meta_key:Vnn } % First we will create a prop list \cs{c_@@_meta_paths_prop} to % handle the \emph{optional argument}. % \iffalse %% Define |\setenumextmeta|. % \fi % \begin{macrocode} \prop_const_from_keyval:Nn \c_@@_meta_paths_prop { {enumext,1} = level-1, {enumext,2} = level-2, {enumext,3} = level-3, {enumext,4} = level-4, {enumext*} = enumext* } % \end{macrocode} % Now we create the user command taking care that \texttt{unknown} % cannot be passed as an argument. % \begin{macrocode} \NewDocumentCommand \setenumextmeta { s O{enumext,1} m +m } { \str_if_eq:eeTF { \tl_trim_spaces:n {#3} } { unknown } { \msg_error:nn { enumext } { prohibited-unknown } } { \bool_if:nTF {#1} { \int_step_inline:nn { 4 } { \@@_add_meta_key:nnn { enumext, ##1 } {#3} {#4} } \@@_add_meta_key:nnn { enumext* } {#3} {#4} } { \@@_add_meta_key:nnn {#2} {#3} {#4} } } } % \end{macrocode} % The internal functions \cs{@@_add_meta_key:nnn} and \cs{@@_def_meta_key:nnn} % will check the \emph{optional argument} and create the \emph{\enquote{meta-key}}. % \begin{macrocode} \cs_new_protected:Npn \@@_add_meta_key:nnn #1 { \tl_set:Nn \l_@@_meta_path_tl {#1} \tl_replace_all:Nnn \l_@@_meta_path_tl { ~ } {} \prop_get:NVNTF \c_@@_meta_paths_prop \l_@@_meta_path_tl \l_@@_meta_path_tl { \@@_def_meta_key:Vnn \l_@@_meta_path_tl } { \msg_error:nnn { enumext } { unknown-set } {#1} \use_none:nn } } \cs_new_protected:Npn \@@_def_meta_key:nnn #1#2#3 { \bool_lazy_or:nnTF { \keys_if_exist_p:nn { enumext / #1 } {#2} } { \keys_if_exist_p:nn { enumext / enumext* } {#2} } { \msg_error:nnn { enumext } { already-defined } {#2} } { \keys_define:nn { enumext / #1 } { #2 .meta:n = {#3}, #2 .value_forbidden:n = true } } } \cs_generate_variant:Nn \@@_def_meta_key:nnn { V } % \end{macrocode} % \end{macro} % % \subsection{The command \cs{foreachkeyans}}\label{cmd:foreachkeyans} % % The command \ics*{foreachkeyans} will execute a \emph{loop} over the \emph{prop list} and return its contents. % The implementation code is adapted from the answer provided by Enrico Gregorio \texttt{(@egreg)} in % \href{https://tex.stackexchange.com/a/721130}{Expand a \texttt{.cs} defined by key inside the function}. % % \begin{macro}{\foreachkeyans, \@@_parse_foreach_keys:nn, % \@@_parse_foreach_keys:n, \@@_foreach_keyans:nn, % \@@_foreach_add_body:n} % We define a set of \mymeta{keys} for command and we will save the % default values ​​of these in \cs{g_@@_foreach_default_keys_tl} to avoid % the use of group. % \iffalse %% Define |\foreachkeyans|. % \fi % \begin{macrocode} \keys_define:nn { enumext / foreach } { before .tl_set:N = \l_@@_foreach_before_tl, before .value_required:n = true, after .tl_set:N = \l_@@_foreach_after_tl, after .value_required:n = true, start .int_set:N = \l_@@_foreach_start_int, start .value_required:n = true, stop .int_set:N = \l_@@_foreach_stop_int, stop .value_required:n = true, step .int_set:N = \l_@@_foreach_step_int, step .value_required:n = true, wrapper .cs_set_protected:Np = \@@_foreach_wrapper:n #1, wrapper .value_required:n = true, sep .tl_set:N = \l_@@_foreach_sep_tl, sep .value_required:n = true, unknown .code:n = { \@@_parse_foreach_keys:n {#1} } } \keys_precompile:nnN { enumext / foreach } { before={},after={},start=1,step=1,stop=0,wrapper=#1,sep={; } } \g_@@_foreach_default_keys_tl % \end{macrocode} % Functions for handling unknown \mymeta{keys}. % \begin{macrocode} \cs_new_protected:Npn \@@_parse_foreach_keys:nn #1#2 { \tl_if_blank:nTF {#2} { \msg_error:nnn { enumext } { for-key-unknown } {#1} } { \msg_error:nnnn { enumext } { for-key-value-unknown } {#1} {#2} } } \cs_new_protected:Npn \@@_parse_foreach_keys:n #1 { \exp_args:NV \@@_parse_foreach_keys:nn \l_keys_key_str {#1} } % \end{macrocode} % We create the command. % \begin{macrocode} \NewDocumentCommand \foreachkeyans { +O{} m } { \@@_foreach_keyans:nn {#1} {#2} } % \end{macrocode} % Finally the internal functions \cs{@@_foreach_keyans:nn} and % \cs{@@_foreach_add_body:n} will loop through the prop list and print % the contents. % \begin{macrocode} \cs_new_protected:Npn \@@_foreach_keyans:nn #1 #2 { \tl_use:N \g_@@_foreach_default_keys_tl \keys_set:nn { enumext / foreach } {#1} \tl_set:Nn \l_@@_foreach_name_prop_tl {#2} \prop_if_exist:cF { g_@@_#2_prop } { \msg_error:nnn { enumext } { undefined-storage-anskey } {#2} } \int_compare:nNnT { \l_@@_foreach_stop_int } = { 0 } { \int_set:Nn \l_@@_foreach_stop_int { \prop_count:c { g_@@_#2_prop } } } \seq_clear:N \l_@@_foreach_print_seq \int_step_function:nnnN { \l_@@_foreach_start_int } { \l_@@_foreach_step_int } { \l_@@_foreach_stop_int } \@@_foreach_add_body:n \seq_use:NV \l_@@_foreach_print_seq \l_@@_foreach_sep_tl } \cs_new_protected:Npn \@@_foreach_add_body:n #1 { \seq_put_right:Ne \l_@@_foreach_print_seq { \exp_not:V \l_@@_foreach_before_tl \@@_foreach_wrapper:n { \prop_item:cn { g_@@_ \l_@@_foreach_name_prop_tl _prop }{#1} } \exp_not:V \l_@@_foreach_after_tl } } % \end{macrocode} % \end{macro} % % \subsection{Messages} % % \iffalse %% Messages. % \fi % Message used by package-load for \mypkg{multicol} and \mypkg{hyperref} % packages. % \begin{macrocode} \msg_new:nnn { enumext } { package-load } { The ~ '#1' ~ package ~ is ~ already ~ loaded. } \msg_new:nnn { enumext } { package-not-load } { The ~ '#1' ~ package ~ will ~ be ~ loaded ~ as ~ a ~ dependency. } \msg_new:nnn { enumext } { package-load-foot } { The ~ '#1' ~ package ~ is ~ loaded ~ with ~ the ~ option ~ '#2'. } % \end{macrocode} % % Message used in the creation of counters by \mypkg*{enumext} package. % \begin{macrocode} \msg_new:nnn { enumext } { counters } { The ~ counter ~ '#1' ~ is ~ already ~ defined ~ by ~ some ~ \\ package ~ or ~ macro, ~ it ~ cannot ~ be ~ continued. } % \end{macrocode} % % Message used by \mykey{align} and \mykey{mark-pos} keys. % \begin{macrocode} \msg_new:nnn { enumext } { unknown-choice } { The ~ value ~ '#3' ~ for ~ '#1' ~ key ~ is ~ invalid ~ use ~ ('#2'). } % \end{macrocode} % % Message used by reserved \myenv*{anskey*} environment by \mypkg*{enumext} % package. % \begin{macrocode} \msg_new:nnnn { enumext } { anskey-env-error } { The ~ '#1' ~ environment ~is ~ reserved ~ by ~\\ 'enumext' ~ package, ~ It~ is~ already~ defined. } { The ~ anskey* ~ environment ~ is ~ defined ~ internally ~ for ~ the ~ 'save-ans' ~ key.\\ } % \end{macrocode} % % Message used in the creation of \emph{prop list} by \mypkg*{enumext} % package. % \begin{macrocode} \msg_new:nnn { enumext } { store-prop } { * ~ Package ~ enumext: ~ Creating ~ \c_backslash_str g_@@_#1_prop ~ \msg_line_context:. } \msg_new:nnn { enumext } { store-seq } { * ~ Package ~ enumext: ~ Creating ~ \c_backslash_str g_@@_#1_seq ~ \msg_line_context:. } \msg_new:nnn { enumext } { store-int } { * ~ Package ~ enumext: ~ Creating ~ \c_backslash_str g_@@_resume_#1_int ~ \msg_line_context:. } \msg_new:nnn { enumext } { prop-seq-int-hook } { * ~ Package ~ enumext: ~ Elements ~ in ~ \c_backslash_str g_@@_#1_prop ~ = ~ #2.\\ * ~ Package ~ enumext: ~ Elements ~ in ~ \c_backslash_str g_@@_#1_seq ~ = ~ #3.\\ * ~ Package ~ enumext: ~ Value ~ off ~ \c_backslash_str g_@@_resume_#1_int ~ = ~ #4. } \msg_new:nnn { enumext } { item-answer-hook } { * ~ Package ~ enumext: ~ Value ~ off ~ \c_backslash_str g_@@_item_number_int ~ = ~ #1.\\ * ~ Package ~ enumext: ~ Value ~ off ~ \c_backslash_str g_@@_item_anskey_int ~ = ~ #2.\\ * ~ Package ~ enumext: ~ Difference ~ item_number_int ~ - ~ item_anskey_int ~ = ~ #3. } % \end{macrocode} % % Message used by \myoarg{key \textnormal{\textcolor{gray}{=}} val} % system and \ics*{setenumext} command. % \begin{macrocode} \msg_new:nnn { enumext } { invalid-key } { The ~ key ~ '#1' ~ is ~ not ~ know ~ the ~ level ~ #2. } \msg_new:nnn { enumext } { unknown-key-family } { Unknown~key~family~`\l_keys_key_str'~for~enumext. } % \end{macrocode} % Messages used in length calculation. % \begin{macrocode} \msg_new:nnn { enumext } { width-negative } { Ignoring ~ negative ~ value ~ '#1=#2' ~ \msg_line_context:.\\ The ~ key ~ '#1'~ accepts ~ values ~ >= ~ 0pt. } \msg_new:nnn { enumext } { width-zero } { Invalid ~ '#1=#2' ~ \msg_line_context:.\\ The ~ key ~ '#1'~ accepts ~ values ~ > ~ 0pt. } % \end{macrocode} % Messages used by \mykey{show-length} key in \myenv*{enumext}. % \begin{macrocode} \msg_new:nnn { enumext } { list-lengths } { **** ~ Lengths ~ used ~ by ~ 'enumext' ~ level ~ '#2' ~ \msg_line_context:~\c_space_tl ****\\ \@@_show_length:nnn { dim } { labelsep } {#1} \@@_show_length:nnn { dim } { labelwidth } {#1} \@@_show_length:nnn { dim } { itemindent } {#1} \@@_show_length:nnn { dim } { leftmargin } {#1} \@@_show_length:nnn { dim } { rightmargin } {#1} \@@_show_length:nnn { dim } { listparindent } {#1} \@@_show_length:nnn { skip } { topsep } {#1} \@@_show_length:nnn { skip } { parsep } {#1} \@@_show_length:nnn { skip } { partopsep } {#1} \@@_show_length:nnn { skip } { itemsep } {#1} **************************************************** } % \end{macrocode} % % Messages used by \mykey{show-length} key in \myenv*{enumext*}, % \myenv*{keyans*} and \myenv*{keyans}. % \begin{macrocode} \msg_new:nnn { enumext } { list-lengths-not-nested } { **** ~ Lengths ~ used ~ by ~ '#2' ~ environment ~ \msg_line_context:~\c_space_tl ****\\ \@@_show_length:nnn { dim } { labelsep } {#1} \@@_show_length:nnn { dim } { labelwidth } {#1} \@@_show_length:nnn { dim } { itemindent } {#1} \@@_show_length:nnn { dim } { leftmargin } {#1} \@@_show_length:nnn { dim } { rightmargin } {#1} \@@_show_length:nnn { dim } { listparindent } {#1} \@@_show_length:nnn { skip } { topsep } {#1} \@@_show_length:nnn { skip } { parsep } {#1} \@@_show_length:nnn { skip } { partopsep } {#1} \@@_show_length:nnn { skip } { itemsep } {#1} **************************************************** } % \end{macrocode} % % Messages used by \mykey{ref} key. % \begin{macrocode} \msg_new:nnn { enumext } { key-ref-empty } { Key ~ 'ref' ~ need ~ a ~ value ~ in ~ '#1'~ \msg_line_context:. } % \end{macrocode} % % Messages used by \mykey{save-ans} key. % \begin{macrocode} \msg_new:nnn { enumext } { save-ans-empty } { Key ~ 'save-ans' ~ need ~ a ~ value ~ in ~ '#1'~ \msg_line_context:. } \msg_new:nnn { enumext } { save-ans-log } { * ~ Package ~ enumext: ~ Start ~ #1\c_space_tl with ~ save-ans=#2 ~ \msg_line_context:. } \msg_new:nnn { enumext } { save-ans-log-hook } { * ~ Package ~ enumext: ~ Stop ~ #1\c_space_tl with ~ save-ans=#2 ~ \msg_line_context:. } \msg_new:nnn { enumext } { save-ans-hook } { Stop ~ storing ~ for ~ 'save-ans=#1' ~ \msg_line_context:. } % \end{macrocode} % % Messages used by the internal system to check answer used by % \mykey{check-ans} key. % \begin{macrocode} \msg_new:nnn { enumext } { need-save-ans } { Key ~ '#1'~ works ~ only ~ with ~ the ~ 'save-ans' ~ key ~ in ~ '#2'~ \msg_line_context:. } \msg_new:nnn { enumext } { items-same-answer } { ****************************************\\ * ~ Package ~ enumext: ~ Checking ~ answers ~ in ~ '#1' ~ for ~ \c_left_brace_str #2 \c_right_brace_str\\ * ~ started ~ #3 ~ and ~ close ~ \msg_line_context: : ~ 'OK', ~ all ~ items ~ with ~ answer.\\ **************************************** } \msg_new:nnn { enumext } { item-greater-answer } { Checking ~ answers ~ in ~ '#1' ~ for ~ \c_left_brace_str #2 \c_right_brace_str\\ started ~ #3 ~ and ~ close ~ \msg_line_context: : ~'NOT ~ OK'\\ Items ~ > ~ Answers. } \msg_new:nnn { enumext } { item-less-answer } { Checking ~ answers ~ in ~ '#1' ~ for ~ \c_left_brace_str #2 \c_right_brace_str\\ started ~ #3 ~ and ~ close ~ \msg_line_context: : ~'NOT ~ OK'\\ Items ~ < ~ Answers. } % \end{macrocode} % Messages used by the internal system to check for % \emph{\enquote{starred}} |\item*| and |\anspic*| commands. % \begin{macrocode} \msg_new:nnn { enumext } { missing-starred } { Missing ~ '\c_backslash_str #1*' ~ #2. } \msg_new:nnn { enumext } { many-starred } { Many ~ '\c_backslash_str #1*' ~ #2. } % \end{macrocode} % Messages used by |\printkeyans*| command. % \begin{macrocode} \msg_new:nnn { enumext } { print-starred } { \c_backslash_str printkeyans*:~ The ~ sequence ~ '#1' ~ already ~ contains ~ #2 ~ environment ~ \msg_line_context:. } % \end{macrocode} % Message for the nesting depth of the environment \myenv*{enumext}. % \begin{macrocode} \msg_new:nnn { enumext } { list-too-deep } { Too ~ deep ~ nesting ~ for ~ 'enumext' ~ \msg_line_context:.~ \\ The ~ maximum ~ level ~ of ~ nesting ~ is ~ 4. } % \end{macrocode} % Messages used by \ics*{anskey}, \myenv*{anskey*} and \ics*{anspic} commands. % \begin{macrocode} \msg_new:nnn { enumext } { anskey-unnumber-item } { Can't ~ store ~ with ~ a ~ unnumbered ~ \c_backslash_str item ~ \msg_line_context:. } \msg_new:nnn { enumext } { anskey-already-stored } { Content ~ already ~ stored ~ for ~ this ~ \c_backslash_str item ~ \msg_line_context:. } \msg_new:nnn { enumext } { anskey-empty-arg } { Can't ~ store ~ empty ~ content ~ \msg_line_context:. } \msg_new:nnn { enumext } { anskey-wrong-place } { Wrong ~ place ~ for ~ command ~ '\c_backslash_str #1' ~ \msg_line_context:.~ \\ '\c_backslash_str #1' ~ works ~ in ~ the ~ environment ~ '#2'. } \msg_new:nnn { enumext } { anskey-nested } { The ~ command ~ \c_backslash_str anskey~ can't ~ be ~ nested ~ \msg_line_context:. } \msg_new:nnn { enumext } { anskey-math-mode } { #1 ~ can't ~ work ~ in ~ math ~ mode ~ \msg_line_context:. } \msg_new:nnn { enumext } { anskey-env-wrong } { The ~ environment ~ anskey* ~ cannot ~ use ~ in ~ '#1' ~ \msg_line_context:. } \msg_new:nnn { enumext } { anspic-wrong-place } { Wrong ~ place ~ for ~ command ~ '\c_backslash_str #1' ~ \msg_line_context:.~ \\ '\c_backslash_str #1' ~ works ~ in ~ the ~ environment ~ '#2'. } \msg_new:nnn { enumext } { command-wrong-place } { Wrong ~ place ~ for ~ command ~ '\c_backslash_str #1' ~ \msg_line_context:.~ \\ '\c_backslash_str #1' ~ works ~ outside ~ the ~ environment ~ '#2'. } \msg_new:nnnn { enumext } { anskey-env-key-unknown } { The ~ key ~ '#1' ~ is ~ unknown ~ by ~ environment~ 'anskey*' ~ and ~ is ~ being ~ ignored. } { The ~ environment ~ 'anskey*' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } \msg_new:nnnn { enumext } { anskey-env-key-value-unknown } { The ~ key ~ '#1=#2' ~ is ~ unknown ~ by ~ environment ~ 'anskey*' ~ and ~ is ~ being ~ ignored. } { The ~ environment ~ 'anskey*' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } \msg_new:nnnn { enumext } { anskey-cmd-key-unknown } { The ~ key ~'#1'~ is ~ unknown ~ by ~ '\c_backslash_str anskey' ~ and ~ is ~ being ~ ignored.} { The ~ command ~'\c_backslash_str anskey' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } \msg_new:nnnn { enumext } { anskey-cmd-key-value-unknown } { The ~ key ~ '#1=#2' ~ is ~ unknown ~ by ~ '\c_backslash_str anskey' ~ and ~ is ~ being ~ ignored. } { The ~ command ~ '\c_backslash_str anskey' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } % \end{macrocode} % % Messages used by \myenv*{keyans}, \myenv*{keyans*} and \myenv*{keyanspic} % environment. % \begin{macrocode} \msg_new:nnn { enumext } { keyans-nested } { The ~ environment ~ 'keyans' ~ can't ~ be ~ nested ~ \msg_line_context:. } \msg_new:nnn { enumext } { keyans-wrong-level } { Wrong ~ level ~ position ~ for ~ 'keyans' ~ \msg_line_context:.~ \\ The ~ environment ~ 'keyans' ~ can ~ only ~ be ~ in ~ the ~ first ~ level. } \msg_new:nnn { enumext } { wrong-place } { Wrong ~ place ~ for ~ '#1' ~ environment ~\msg_line_context:.~ \\ '#1' ~ is ~ only ~ found ~ with ~ '#2' ~ in ~ 'enumext. } \msg_new:nnn { enumext } { keyanspic-nested } { The ~ environment ~ 'keyanspic' ~ can't ~ be ~ nested~ \msg_line_context:.~. } \msg_new:nnn { enumext } { keyanspic-wrong-level } { Wrong ~ level ~ position ~ for ~ 'keyanspic' ~ \msg_line_context:.~ \\ The ~ environment ~ 'keyans' ~ can ~ only ~ be ~ in ~ the ~ first ~ level. } \msg_new:nnn { enumext } { keyanspic-item-cmd } { Can't ~ use ~ \c_backslash_str item ~ in ~ keyanspic ~ \msg_line_context:. } \msg_new:nnnn { enumext } { keyans-unknown-key } { The ~ key ~ '#1' ~ is ~ unknown ~ by ~ environment~ '\l_@@_envir_name_tl' ~ and ~ is ~ being ~ ignored. } { The ~ environment ~ '\l_@@_envir_name_tl' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } \msg_new:nnnn { enumext } { keyans-unknown-key-value } { The ~ key ~ '#1=#2' ~ is ~ unknown ~ by ~ environment ~ '\l_@@_envir_name_tl' ~ and ~ is ~ being ~ ignored. } { The ~ environment ~ '\l_@@_envir_name_tl' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } % \end{macrocode} % % Message used by unknown \mymeta{keys} in \myenv*{enumext*}. % environment. % \begin{macrocode} \msg_new:nnnn { enumext } { starred-unknown-key } { The ~ key ~ '#1' ~ is ~ unknown ~ by ~ environment~ '\l_@@_envir_name_tl' ~ and ~ is ~ being ~ ignored. } { The ~ environment ~ '\l_@@_envir_name_tl' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } \msg_new:nnnn { enumext } { starred-unknown-key-value } { The ~ key ~ '#1=#2' ~ is ~ unknown ~ by ~ environment ~ '\l_@@_envir_name_tl' ~ and ~ is ~ being ~ ignored. } { The ~ environment ~ '\l_@@_envir_name_tl' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1'.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } % \end{macrocode} % Message used by unknown \mymeta{keys} in \myenv*{enumext} % environment. % \begin{macrocode} \msg_new:nnnn { enumext } { standar-unknown-key } { The ~ key ~ '#1' ~ is ~ unknown ~ by ~ environment ~ '\l_@@_envir_name_tl' \c_space_tl ~ on ~ level ~ \int_use:N \l_@@_level_int \c_space_tl and ~ is ~ being ~ ignored. } { The ~ environment ~ '\l_@@_envir_name_tl' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1' ~ on ~ level ~ \int_use:N \l_@@_level_int.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } \msg_new:nnnn { enumext } { standar-unknown-key-value } { The ~ key ~ '#1=#2' ~ is ~ unknown ~ by ~ environment ~ '\l_@@_envir_name_tl' \c_space_tl ~ on ~ level ~ \int_use:N \l_@@_level_int \c_space_tl and ~ is ~ being ~ ignored. } { The ~ environment ~ '\l_@@_envir_name_tl' ~ does ~ not ~ have ~ a ~ key ~ called ~'#1' ~ on ~ level ~ \int_use:N \l_@@_level_int.\\ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly. } % \end{macrocode} % Message used by unknown \mymeta{keys} in \ics*{foreachkeyans}. % \begin{macrocode} \msg_new:nnnn { enumext } { for-key-unknown } { The~key~'#1'~is~unknown~by~'\c_backslash_str foreachkeyans'~and~is~being~ignored.} { The~command~'\c_backslash_str foreachkeyans'~does~not~have~a~key~called~'#1'.\\ Check~that~you~have~spelled~the~key~name~correctly. } \msg_new:nnnn { enumext } { for-key-value-unknown } { The~key~'#1=#2'~is~unknown~by~'\c_backslash_str foreachkeyans'~and~is~being~ignored. } { The~command~'\c_backslash_str foreachkeyans'~does~not~have~a~key~called~'#1'.\\ Check~that~you~have~spelled~the~key~name~correctly. } % \end{macrocode} % % Messages used by \ics*{getkeyans} command. % \begin{macrocode} \msg_new:nnn { enumext } { undefined-storage-anskey } { Storage ~ named ~ '#1' ~ is ~ not ~ defined ~ \msg_line_context:. } % \end{macrocode} % % Messages used by \ics*{miniright} command. % \begin{macrocode} \msg_new:nnn { enumext } { missing-miniright } { Missing ~ '\c_backslash_str miniright' ~ in ~ \msg_line_context:.\\ The ~ key ~ 'mini-env' ~ need ~ '\c_backslash_str miniright'. } \msg_new:nnn { enumext } { wrong-miniright-place } { Wrong ~ place ~ for ~ '\c_backslash_str miniright' ~ \msg_line_context:.~ \\ Works ~ in ~ 'enumext' ~ and ~ 'keyans' ~ with ~ key ~ 'mini-env'. } \msg_new:nnn { enumext } { wrong-miniright-use } { Wrong ~ use ~ for ~ '\c_backslash_str miniright' ~ \msg_line_context:.~ \\ '\c_backslash_str miniright' ~ need ~ a ~ key ~ 'mini-env'. } \msg_new:nnn { enumext } { wrong-miniright-starred } { Can't ~ use ~ \c_backslash_str miniright ~ in ~ starred ~ environments ~ \msg_line_context:. } \msg_new:nnn { enumext } { many-miniright-used } { Can't ~ use ~ \c_backslash_str miniright ~ more ~ than ~ once ~ \msg_line_context:. } % \end{macrocode} % Messages used by \ics*{setenumextmeta} command. % \begin{macrocode} \msg_new:nnn { enumext } { unknown-set } { Argument ~ [#1] ~ is ~ unknown ~ by ~ \c_backslash_str setenumextmeta ~ \msg_line_context:. } \msg_new:nnn { enumext } { already-defined } { The ~ key ~ '#1' ~ is ~ already ~ defined ~ \msg_line_context:. } \msg_new:nnn { enumext } { prohibited-unknown } { The ~ name ~ 'unknown' ~ can't ~ be ~ chosen~ for ~ a ~ meta ~ key ~ \msg_line_context:. } % \end{macrocode} % Messages used by \myenv*{enumext*} and \myenv*{keyans*} environments. % \begin{macrocode} \msg_new:nnn { enumext } { nested } { The ~ environment ~ \l_@@_envir_name_tl \c_space_tl can't ~ be ~ nested ~ \msg_line_context:. } \msg_new:nnn { enumext } { nested-horizontal } { The ~ environment ~ \l_@@_envir_name_tl \c_space_tl can't ~ be ~ nested ~ in ~ '#1' ~ \msg_line_context:. } \msg_new:nnn { enumext } { item-joined } { Items ~ joined ~ (#1) ~ > ~ #2 ~ columns ~\msg_line_context:. } \msg_new:nnn { enumext } { item-joined-columns } { Not ~ space ~ to ~ join ~ items ~ (#1) ~ > ~ #2 ~\msg_line_context:. } % \end{macrocode} % \subsection{Finish package} % % Finish package implementation. % % \begin{macrocode} \file_input_stop: % % \end{macrocode} % \Finale