summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2024-11-01 21:26:09 +0000
committerKarl Berry <karl@freefriends.org>2024-11-01 21:26:09 +0000
commitb52be2f59db36993de24df6c7e61d2ce674d528a (patch)
tree08f80abba884a45632000224c0ce449165b3b63a
parent470dbc5d151043007149361d8e04ec509c9f5faf (diff)
enumext (1nov24)
git-svn-id: svn://tug.org/texlive/trunk@72740 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/latex/enumext/README.md69
-rw-r--r--Master/texmf-dist/doc/latex/enumext/enumext.pdfbin0 -> 1643633 bytes
-rw-r--r--Master/texmf-dist/source/latex/enumext/enumext.dtx15804
-rw-r--r--Master/texmf-dist/source/latex/enumext/enumext.ins53
-rw-r--r--Master/texmf-dist/tex/latex/enumext/enumext.sty6115
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check2
-rw-r--r--Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/enumext.tlpsrc0
8 files changed, 22043 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/enumext/README.md b/Master/texmf-dist/doc/latex/enumext/README.md
new file mode 100644
index 00000000000..8ead16580f9
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/enumext/README.md
@@ -0,0 +1,69 @@
+## enumext — Enumerate exercise sheets
+
+Release v1.0 \[2024-11-01\]
+
+## Description
+
+This package provides enumerated list environments compatible with
+_tagging_ PDF for creating “simple exercise sheets” along with
+“multiple choice questions”, storing the “answers” to these in memory
+using <code>&langle;multicol&rangle;</code> and <code>&langle;scontents&rangle;</code> packages.
+
+## Requirements
+
+The minimum requirement is LaTeX release 2024-11-01. Loads and depends
+on updated versions of:
+
+- [scontents](https://ctan.org/pkg/scontents)
+- [multicol](https://ctan.org/pkg/multicol)
+
+## Installation
+
+The <code>&langle;enumext&rangle;</code> package is present in TeX Live and MiKTeX, use the
+package manager to install.
+
+For manual installation, download [enumext.zip](http://mirrors.ctan.org/macros/latex/contrib/enumext.zip) and unzip it,
+then run:
+
+```
+$ luatex enumext.ins
+```
+
+and move all files to appropriate locations:
+
+```
+ enumext.sty -> TDS:tex/latex/enumext/enumext.sty
+ enumext.pdf -> TDS:doc/latex/enumext/enumext.pdf
+ README.md -> TDS:doc/latex/enumext/README.md
+ enumext.dtx -> TDS:source/latex/enumext/enumext.dtx
+ enumext.ins -> TDS:source/latex/enumext/enumext.ins
+```
+
+then run `mktexlsr`. To produce the documentation with source code run `arara enumext.dtx`.
+
+## Examples
+
+The file <code>&langle;enumext.pdf&rangle;</code> contains attached examples, which can be extracted
+from the PDF viewer or from the command line by running:
+
+```
+$ pdfdetach -saveall enumext.pdf
+```
+
+and then you can use the excellent `arara` tool to compile them.
+
+## License
+
+The <code>&langle;enumext&rangle;</code> package may be modified and distributed under the terms and
+conditions of the [LaTeX Project Public License](https://www.latex-project.org/lppl/), version 1.3c or greater.
+
+## Contents
+
+- &langle;`README.md`&rangle; \(this file\)
+- &langle;`enumext.pdf`&rangle; \(documentation\)
+- &langle;`enumext.dtx`&rangle; \(master file that produced all files\)
+- &langle;`enumext.ins`&rangle; \(installer to extract all files\)
+
+## Author and copyright
+
+Copyright &#169; 2024 by Pablo González L <pablgonz@educarchile.cl>
diff --git a/Master/texmf-dist/doc/latex/enumext/enumext.pdf b/Master/texmf-dist/doc/latex/enumext/enumext.pdf
new file mode 100644
index 00000000000..0a70a539d52
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/enumext/enumext.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/latex/enumext/enumext.dtx b/Master/texmf-dist/source/latex/enumext/enumext.dtx
new file mode 100644
index 00000000000..5cc3a17b60f
--- /dev/null
+++ b/Master/texmf-dist/source/latex/enumext/enumext.dtx
@@ -0,0 +1,15804 @@
+% \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 <pablgonz@educarchile.cl>
+%
+% 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}
+%</driver>
+% \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
+%</example>
+% \fi
+%
+% The package is loaded in the usual way:
+%
+% \iffalse
+%<*example>
+% \fi
+\begin{examplecode}[frame=single]
+\usepackage{enumext}
+\end{examplecode}
+% \iffalse
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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
+%</example>
+% \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:
+%</package>
+% \end{macrocode}
+% \Finale
diff --git a/Master/texmf-dist/source/latex/enumext/enumext.ins b/Master/texmf-dist/source/latex/enumext/enumext.ins
new file mode 100644
index 00000000000..f4c45001493
--- /dev/null
+++ b/Master/texmf-dist/source/latex/enumext/enumext.ins
@@ -0,0 +1,53 @@
+\input docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\preamble
+
+Copyright (C) 2024 by Pablo González L <pablgonz@educarchile.cl>
+
+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.pdf , enumext.ins, enumext.dtx
+and the files generated from them.
+
+The released version of this package is available from CTAN.
+
+------------------------------------------------------------------------
+
+The development version of the package can be found at
+
+ https://github.com/pablgonz/enumext/
+
+for those people who are interested.
+
+------------------------------------------------------------------------
+
+\endpreamble
+% Stop docstrip adding \endinput (from l3doc.dtx)
+\postamble
+\endpostamble
+\usedir{tex/latex/enumext}%
+\generate{\file{enumext.sty}{\from{enumext.dtx}{package}}}%
+\Msg{*****************************************************************}%
+\Msg{*}
+\Msg{* To finish the installation you have to move the files into a }
+\Msg{* TDS directory searched by your TeX distribution.}
+\Msg{*}
+\Msg{* To produce the documentation with source code run arara }%
+\Msg{* on file enumext.dtx }%
+\Msg{*}
+\Msg{* Happy TeXing!}
+\Msg{*}
+\Msg{*****************************************************************}%
+
+\endbatchfile
diff --git a/Master/texmf-dist/tex/latex/enumext/enumext.sty b/Master/texmf-dist/tex/latex/enumext/enumext.sty
new file mode 100644
index 00000000000..a810dde276c
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/enumext/enumext.sty
@@ -0,0 +1,6115 @@
+%%
+%% This is file `enumext.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% enumext.dtx (with options: `package')
+%%
+%% Copyright (C) 2024 by Pablo González L <pablgonz@educarchile.cl>
+%%
+%% 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.pdf , enumext.ins, enumext.dtx
+%% and the files generated from them.
+%%
+%% The released version of this package is available from CTAN.
+%%
+%% ------------------------------------------------------------------------
+%%
+%% The development version of the package can be found at
+%%
+%% https://github.com/pablgonz/enumext/
+%%
+%% for those people who are interested.
+%%
+%% ------------------------------------------------------------------------
+%%
+\NeedsTeXFormat{LaTeX2e}[2024-11-01]
+\ProvidesExplPackage {enumext} {2024-11-01} {1.0} {Enumerate exercise sheets}
+\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}
+ }
+ }
+%% Variable for levels and nesting off all environments and \anskey.
+\int_new:N \l__enumext_level_int
+\int_new:N \l__enumext_level_h_int
+\int_new:N \l__enumext_anskey_level_int
+\int_new:N \l__enumext_keyans_level_int
+\int_new:N \l__enumext_keyans_level_h_int
+\int_new:N \l__enumext_keyans_pic_level_int
+%% Internal vars for levels and nesting off all environments.
+\bool_new:N \l__enumext_starred_bool
+\bool_new:N \g__enumext_starred_bool
+\bool_new:N \l__enumext_starred_first_bool
+\bool_new:N \l__enumext_standar_bool
+\bool_new:N \g__enumext_standar_bool
+\bool_new:N \l__enumext_standar_first_bool
+\bool_new:N \l__enumext_anskey_env_bool
+\bool_new:N \l__enumext_keyans_env_bool
+\tl_new:N \g__enumext_start_line_tl
+\tl_new:N \g__enumext_envir_name_tl
+\tl_new:N \l__enumext_envir_name_tl
+%% Variable for counters
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \tl_new:c { l__enumext_counter_#1_tl }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \__enumext_tmp:n {#1} }
+%% Variables used by |ref| key.
+\tl_const:Nn \c__enumext_counter_style_tl
+ { { arabic } { roman } { Roman } { alph } { Alph } }
+\tl_new:N \l__enumext_ref_key_arg_tl
+\tl_new:N \l__enumext_ref_the_count_tl
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \tl_new:c { l__enumext_renew_the_count_#1_tl }
+ \tl_new:c { l__enumext_the_counter_#1_tl }
+ \tl_set:ce { l__enumext_the_counter_#1_tl } { \exp_not:c { theenumX#1 } }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \__enumext_tmp:n {#1} }
+%% Variables used by |series|, |resume| and |resume*| keys implementation.
+\int_new:N \g__enumext_resume_int
+\int_new:N \g__enumext_resume_vii_int
+\tl_new:N \l__enumext_resume_name_tl
+\bool_new:N \l__enumext_resume_active_bool
+\tl_new:N \g__enumext_standar_series_tl
+\tl_new:N \g__enumext_starred_series_tl
+%% Variables used by |label|, |ref| and |widest| keys.
+\dim_new:N \l__enumext_current_widest_dim
+\tl_new:N \g__enumext_counter_styles_tl
+\tl_new:N \g__enumext_widest_label_tl
+\box_new:N \l__enumext_label_width_by_box
+%% 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.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \bool_new:c { l__enumext_leftmargin_tmp_#1_bool }
+ \dim_new:c { l__enumext_leftmargin_tmp_#1_dim }
+ \dim_new:c { l__enumext_leftmargin_#1_dim }
+ \dim_new:c { l__enumext_itemindent_#1_dim }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \__enumext_tmp:n {#1} }
+%% Variables used by |columns| and |align| keys in |enumext| and |keyans| environments.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \skip_new:c { l__enumext_multicols_above_#1_skip }
+ \skip_new:c { l__enumext_multicols_below_#1_skip }
+ \skip_new:c { g__enumext_multicols_right_#1_skip }
+ \str_new:c { l__enumext_align_label_pos_#1_str }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v } { \__enumext_tmp:n {#1} }
+%% Variables used by |miniright|, |mini-env|, |mini-sep| and |\miniright|.
+\int_new:N \g__enumext_minipage_stat_int
+\skip_new:N \l__enumext_minipage_temp_skip
+\skip_new:N \l__enumext_minipage_left_skip
+\skip_new:N \l__enumext_minipage_right_skip
+\skip_new:N \l__enumext_minipage_after_skip
+\skip_new:N \g__enumext_minipage_right_skip
+\skip_new:N \g__enumext_minipage_after_skip
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \dim_new:c { l__enumext_minipage_left_#1_dim }
+ \bool_new:c { l__enumext_minipage_active_#1_bool }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v, vii, viii } { \__enumext_tmp:n {#1} }
+%% Internal variables used by |wrap-label|, |start*|, |start|, |align|, |above| and |below| keys.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \bool_new:c { l__enumext_wrap_label_#1_bool }
+ \bool_new:c { l__enumext_wrap_label_opt_#1_bool }
+ \int_new:c { l__enumext_start_#1_int }
+ \tl_new:c { l__enumext_fake_item_indent_#1_tl }
+ \tl_new:c { l__enumext_label_fill_left_#1_tl }
+ \tl_new:c { l__enumext_label_fill_right_#1_tl }
+ \bool_new:c { l__enumext_vspace_a_star_#1_bool }
+ \bool_new:c { l__enumext_vspace_b_star_#1_bool }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v, vii, viii } { \__enumext_tmp:n {#1} }
+%% Variables used by |save-ans| key.
+\bool_new:N \l__enumext_store_active_bool
+\tl_new:N \l__enumext_store_name_tl
+\tl_new:N \g__enumext_store_name_tl
+\tl_new:N \l__enumext_store_anskey_arg_tl
+\tl_new:N \l__enumext_store_anskey_env_tl
+\tl_new:N \l__enumext_store_anskey_opt_tl
+\tl_new:N \l__enumext_store_current_label_tl
+\tl_new:N \l__enumext_store_current_opt_arg_tl
+\tl_new:N \l__enumext_store_current_label_tmp_tl
+%% Variables used by |\setenumext|.
+\tl_new:N \l__enumext_setkey_tmpa_tl
+\tl_new:N \l__enumext_setkey_tmpb_tl
+\int_new:N \l__enumext_setkey_tmpa_int
+\seq_new:N \l__enumext_setkey_tmpa_seq
+\seq_new:N \l__enumext_setkey_tmpb_seq
+\tl_new:N \l__enumext_meta_path_tl
+\seq_new:N \l__enumext_foreach_print_seq
+\tl_new:N \l__enumext_foreach_name_prop_tl
+\tl_new:N \g__enumext_foreach_default_keys_tl
+%% Variables used by |\printkeyans|, |mark-pos|, |item-sym*|, |save-key| and storing structure in |enumext| and |enumext*|.
+\tl_new:N \l__enumext_print_keyans_starred_tl
+\bool_new:N \l__enumext_print_keyans_star_bool
+\str_new:N \l__enumext_mark_position_str
+\tl_new:N \g__enumext_item_symbol_aux_tl
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \tl_new:c { l__enumext_print_keyans_#1_tl }
+ \tl_new:c { l__enumext_store_save_key_#1_tl }
+ \bool_new:c { l__enumext_store_save_key_#1_bool }
+ \bool_new:c { l__enumext_store_upper_level_#1_bool }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, vii } { \__enumext_tmp:n {#1} }
+%% Variables used by |\anspic| and |keyanspic|.
+\seq_new:N \l__enumext_anspic_args_seq
+\dim_new:N \l__enumext_anspic_mini_width_dim
+\int_new:N \l__enumext_anspic_above_int
+\int_new:N \l__enumext_anspic_below_int
+\bool_new:N \l__enumext_anspic_label_above_bool
+\str_new:N \l__enumext_anspic_mini_pos_str
+\skip_new:N \g__enumext_keyans_pic_parsep_skip
+\box_new:N \l__enumext_anspic_label_box
+\box_new:N \l__enumext_anspic_body_box
+\dim_new:N \l__enumext_anspic_label_htdp_dim
+\dim_new:N \l__enumext_anspic_body_htdp_dim
+%% Variables used by check-answer mechanism, |check-ans| and |no-store| keys.
+\bool_new:N \l__enumext_check_answers_bool
+\bool_new:N \g__enumext_check_ans_key_bool
+\tl_new:N \l__enumext_check_start_line_env_tl
+\int_new:N \g__enumext_check_starred_cmd_int
+\int_new:N \g__enumext_item_anskey_int
+\int_new:N \g__enumext_item_number_int
+\bool_new:N \l__enumext_item_number_bool
+\int_new:N \g__enumext_item_answer_diff_int
+%% Variables used for hyperref detection.
+\bool_new:N \l__enumext_hyperref_bool
+\bool_new:N \l__enumext_footnotes_key_bool
+%% Variables used by |save-ref| key (internal label and ref).
+\tl_new:N \l__enumext_newlabel_arg_one_tl
+\tl_new:N \l__enumext_newlabel_arg_two_tl
+\tl_new:N \l__enumext_write_aux_file_tl
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \tl_new:c { l__enumext_label_copy_#1_tl }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v, vi, vii, viii } { \__enumext_tmp:n {#1} }
+%% Variables used by |footnote| redefinition.
+\int_new:N \g__enumext_footnote_standar_int
+\int_new:N \g__enumext_footnote_starred_int
+\seq_new:N \g__enumext_footnote_standar_arg_seq
+\seq_new:N \g__enumext_footnote_starred_arg_seq
+\seq_new:N \g__enumext_footnote_standar_int_seq
+\seq_new:N \g__enumext_footnote_starred_int_seq
+%% Variables used by |enumext*| and |keyans*| environments.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \bool_new:c { l__enumext_item_starred_#1_bool }
+ \int_new:c { l__enumext_item_column_pos_#1_int }
+ \int_new:c { g__enumext_item_count_all_#1_int }
+ \int_new:c { l__enumext_joined_item_#1_int }
+ \int_new:c { l__enumext_joined_item_aux_#1_int }
+ \int_new:c { l__enumext_tmpa_#1_int }
+ \dim_new:c { l__enumext_tmpa_#1_dim }
+ \box_new:c { l__enumext_item_text_#1_box }
+ \dim_new:c { l__enumext_joined_width_#1_dim }
+ \dim_new:c { l__enumext_item_width_#1_dim }
+ \tl_new:c { g__enumext_item_symbol_aux_#1_tl }
+ \str_new:c { l__enumext_align_label_#1_str }
+ \bool_new:c { g__enumext_minipage_active_#1_bool }
+ \box_new:c { l__enumext_miniright_code_#1_box }
+ \bool_new:c { g__enumext_minipage_center_#1_bool }
+ \dim_new:c { g__enumext_minipage_right_#1_dim }
+ \skip_new:c { g__enumext_minipage_right_#1_skip }
+ }
+\clist_map_inline:nn { vii, viii } { \__enumext_tmp:n {#1} }
+\clist_const:Nn \c__enumext_all_envs_clist
+ {
+ {level-1}{i}, {level-2}{ii}, {level-3}{iii}, {level-4}{iv},
+ {keyans}{v}, {enumext*}{vii}, {keyans*}{viii}
+ }
+\cs_generate_variant:Nn \keys_precompile:nnN { neN }
+\cs_generate_variant:Nn \seq_use:Nn { NV }
+%% A internal "hooks" functions used for copying and execute code.
+\cs_new_protected:Npn \__enumext_at_begin_document:n #1
+ {
+ \hook_gput_code:nnn {begindocument} {enumext} { #1 }
+ }
+\cs_new_protected:Npn \__enumext_after_env:nn #1 #2
+ {
+ \hook_gput_code:nnn {env/#1/after} {enumext} {#2}
+ }
+\cs_new_protected:Npn \__enumext_before_env:nn #1 #2
+ {
+ \hook_gput_code:nnn {env/#1/before} {enumext} {#2}
+ }
+%% Function to check current level.
+\cs_new:Nn \__enumext_level:
+ {
+ \int_to_roman:n { \l__enumext_level_int }
+ }
+%% Function to check integer variables used by |start| and |widest| keys.
+\prg_new_protected_conditional:Npnn \__enumext_if_is_int:n #1 { T, F, TF }
+ {
+ \regex_match:nnTF { ^[\+\-]?[\d]+$ } {#1} % $
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+%% Regex for replace '*' for |ref| key.
+\cs_new_protected:Nn \__enumext_regex_counter_style:
+ {
+ \tl_map_inline:Nn \c__enumext_counter_style_tl
+ {
+ \regex_replace_once:nnN { \c{##1}\* }
+ { \c{##1}\cB{\u{l__enumext_ref_the_count_tl}\cE} } \l__enumext_ref_key_arg_tl
+ }
+ }
+%% Function to show list lengths used by |show-length| key.
+\cs_new:Npn \__enumext_show_length:nnn #1 #2 #3
+ {
+ * ~ #2
+ \prg_replicate:nn { 14 - \str_count:n {#2} } { ~ }
+ = ~ \use:c { #1_use:c } { l__enumext_#2_#3_#1 } \\
+ }
+%% Remove last skip or kern.
+\cs_new_protected:Nn \__enumext_unskip_unkern:
+ {
+ \int_case:nnT { \lastnodetype }
+ {
+ { 11 }{ \unskip }
+ { 12 }{ \unkern }
+ }
+ }
+%% Function to check/set current environment for |enumext| and |enumext*|.
+\cs_new_protected:Nn \__enumext_is_not_nested:
+ {
+ \str_case:en { \@currenvir }
+ {
+ {enumext}
+ {
+ \tl_set:Nn \l__enumext_envir_name_tl { enumext }
+ \bool_lazy_and:nnT
+ { \bool_not_p:n { \g__enumext_standar_bool } }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 0 } }
+ {
+ \bool_gset_true:N \g__enumext_standar_bool
+ }
+ }
+ {enumext*}
+ {
+ \tl_set:Nn \l__enumext_envir_name_tl { enumext* }
+ \bool_lazy_and:nnT
+ { \bool_not_p:n { \g__enumext_starred_bool } }
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 0 } }
+ {
+ \bool_gset_true:N \g__enumext_starred_bool
+ }
+ }
+ }
+ }
+%% Function to check/set first level vars for |enumext| and |enumext*|.
+\cs_new_protected:Nn \__enumext_is_on_first_level:
+ {
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \g__enumext_standar_bool }
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 1 } }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 0 } }
+ }
+ {
+ \bool_set_true:N \l__enumext_standar_first_bool
+ \bool_set_true:N \l__enumext_anskey_env_bool
+ \tl_gset:Nn \g__enumext_envir_name_tl { enumext }
+ \tl_gset:Ne \g__enumext_start_line_tl
+ {
+ on ~ line ~ \exp_not:V \inputlineno
+ }
+ }
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \g__enumext_starred_bool }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 1 } }
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 0 } }
+ }
+ {
+ \bool_set_true:N \l__enumext_starred_first_bool
+ \bool_set_true:N \l__enumext_anskey_env_bool
+ \tl_gset:Nn \g__enumext_envir_name_tl { enumext* }
+ \tl_gset:Ne \g__enumext_start_line_tl
+ {
+ on ~ line ~ \exp_not:V \inputlineno
+ }
+ }
+ }
+%% Function to save the current name and start line for |keyans|, |keyans*| and |keyanspic|.
+\cs_new_protected:Nn \__enumext_keyans_name_and_start:
+ {
+ \str_case:en { \@currenvir }
+ {
+ {keyans}
+ {
+ \tl_set:Nn \l__enumext_envir_name_tl { keyans }
+ \tl_set:Ne \l__enumext_check_start_line_env_tl
+ {
+ in ~ 'keyans' ~ start ~ on ~ line ~ \exp_not:V \inputlineno
+ }
+ }
+ {keyans*}
+ {
+ \tl_set:Nn \l__enumext_envir_name_tl { keyans* }
+ \tl_set:Ne \l__enumext_check_start_line_env_tl
+ {
+ in ~ 'keyans*' ~ start ~ on ~ line ~ \exp_not:V \inputlineno
+ }
+ }
+ {keyanspic}
+ {
+ \tl_set:Nn \l__enumext_envir_name_tl { keyanspic }
+ \tl_set:Ne \l__enumext_check_start_line_env_tl
+ {
+ in ~ 'keyanspic' ~ start ~ on ~ line ~ \exp_not:V \inputlineno
+ }
+ }
+ }
+ }
+%% Reset all global vars after use in hook function.
+\cs_new_protected:Nn \__enumext_reset_global_vars:
+ {
+ \__enumext_reset_global_int:
+ \__enumext_reset_global_bool:
+ \__enumext_reset_global_tl:
+ }
+\cs_new_protected:Nn \__enumext_reset_global_int:
+ {
+ \int_gzero:N \g__enumext_item_number_int
+ \int_gzero:N \g__enumext_item_anskey_int
+ \int_gzero:N \g__enumext_item_answer_diff_int
+ }
+\cs_new_protected:Nn \__enumext_reset_global_bool:
+ {
+ \bool_gset_false:N \g__enumext_check_ans_key_bool
+ \bool_gset_false:N \g__enumext_standar_bool
+ \bool_gset_false:N \g__enumext_starred_bool
+ }
+\cs_new_protected:Nn \__enumext_reset_global_tl:
+ {
+ \tl_gclear:N \g__enumext_store_name_tl
+ \tl_gclear:N \g__enumext_start_line_tl
+ \tl_gclear:N \g__enumext_envir_name_tl
+ }
+%% Write all global vars after use in hook function.
+\cs_new_protected:Nn \__enumext_log_global_vars:
+ {
+ \msg_log:nneeee { enumext } { prop-seq-int-hook }
+ { \g__enumext_store_name_tl }
+ { \prop_count:c { g__enumext_ \g__enumext_store_name_tl _prop } }
+ { \seq_count:c { g__enumext_ \g__enumext_store_name_tl _seq } }
+ { \int_use:c { g__enumext_resume_ \g__enumext_store_name_tl _int } }
+ }
+%% Write all global vars for check-answer after use in hook function.
+\cs_new_protected:Nn \__enumext_log_answer_vars:
+ {
+ \msg_log:nneee { enumext } { item-answer-hook }
+ { \int_use:N \g__enumext_item_number_int }
+ { \int_use:N \g__enumext_item_anskey_int }
+ { \int_eval:n { \g__enumext_item_number_int - \g__enumext_item_anskey_int} }
+ }
+%% Copy |list| environment and |\item| command.
+\__enumext_at_begin_document:n
+ {
+ \cs_new_eq:NN \__enumext_start_list:nn \list
+ \cs_new_eq:NN \__enumext_stop_list: \endlist
+ \NewCommandCopy \__enumext_item_std:w \item
+ }
+%% Copy |minipage| environment.
+\__enumext_at_begin_document:n
+ {
+ \cs_new_eq:NN \__enumext_minipage:w \minipage
+ \cs_new_eq:NN \__enumext_endminipage: \endminipage
+ }
+%% Detection off |hyperref| package with |hyperfootnotes=true|.
+\hook_gput_code:nnn { begindocument } { enumext } { \__enumext_after_hyperref: }
+\hook_gset_rule:nnnn { begindocument } { enumext } { after } { hyperref }
+\cs_new_protected:Nn \__enumext_after_hyperref:
+ {
+ \IfPackageLoadedTF { hyperref }
+ {
+ \msg_info:nnn { enumext } { package-load } { hyperref }
+ \bool_set_true:N \l__enumext_hyperref_bool
+ \IfHyperBoolean{hyperfootnotes}
+ {
+ \bool_set_true:N \l__enumext_footnotes_key_bool
+ }
+ { }
+ }
+ { }
+%% Detection off |footnotehyper| package.
+ \bool_if:NT \l__enumext_footnotes_key_bool
+ {
+ \IfPackageLoadedTF { footnotehyper }
+ {
+ \msg_info:nnn { enumext } { package-load } { footnotehyper }
+ }
+ {
+ \bool_set_false:N \l__enumext_footnotes_key_bool
+ }
+ }
+ \bool_if:NTF \l__enumext_hyperref_bool
+ {
+ \cs_new_eq:NN \__enumext_hypertarget:nn \hypertarget
+ \cs_new_eq:NN \__enumext_phantomsection: \phantomsection
+ }
+ {
+ \cs_new_eq:NN \__enumext_hypertarget:nn \use_none:nn
+ \cs_new_eq:NN \__enumext_phantomsection: \prg_do_nothing:
+ }
+ }
+%% Write internal |label| in |.aux| file for |save-ref| key.
+\cs_new_protected:Npn \__enumext_newlabel:nn #1 #2
+ {
+ \protected@write \@auxout { }
+ {
+ \token_to_str:N \newlabel {#1}
+ {
+ {#2}
+ \bool_if:NT \l__enumext_hyperref_bool
+ { { \thepage } {#2} {#1} }
+ { }
+ }
+ }
+ \__enumext_hypertarget:nn {#1} { }
+ \__enumext_phantomsection:
+ }
+%% Redefining |\footnote| for key |mini-env| in |enumext| and |keyans| environments.
+\cs_new_protected:Nn \__enumext_footnotetext:nn
+ {
+ \footnotetext[#1]{#2}
+ }
+\cs_new_protected:Nn \__enumext_renew_footnote:
+ {
+ \RenewDocumentCommand \footnote { o +m }
+ {
+ \tl_if_novalue:nTF {##1}
+ {
+ \stepcounter{footnote}
+ \int_gset_eq:Nc \g__enumext_footnote_standar_int { c@footnote }
+ }
+ {
+ \int_gset:Nn \g__enumext_footnote_standar_int { ##1 }
+ }
+ \footnotemark [ \g__enumext_footnote_standar_int ]
+ \seq_gput_right:Nn \g__enumext_footnote_standar_arg_seq { ##2 }
+ \seq_gput_right:NV
+ \g__enumext_footnote_standar_int_seq \g__enumext_footnote_standar_int
+ }
+ }
+\cs_new_protected:Nn \__enumext_print_footnote:
+ {
+ \seq_if_empty:NF \g__enumext_footnote_standar_int_seq
+ {
+ \seq_map_pairwise_function:NNN
+ \g__enumext_footnote_standar_int_seq
+ \g__enumext_footnote_standar_arg_seq
+ \__enumext_footnotetext:nn
+ }
+ \seq_gclear:N \g__enumext_footnote_standar_arg_seq
+ \seq_gclear:N \g__enumext_footnote_standar_int_seq
+ }
+%% Redefining |\footnote| for |enumext*| and |keyans*| environments.
+\cs_new_protected:Nn \__enumext_renew_footnote_mini:
+ {
+ \RenewDocumentCommand \footnote { o +m }
+ {
+ \tl_if_novalue:nTF {##1}
+ {
+ \stepcounter{footnote}
+ \int_gset_eq:Nc \g__enumext_footnote_starred_int { c@footnote }
+ }
+ {
+ \int_gset:Nn \g__enumext_footnote_starred_int { ##1 }
+ }
+ \footnotemark [ \g__enumext_footnote_starred_int ]
+ \seq_gput_right:Nn \g__enumext_footnote_starred_arg_seq { ##2 }
+ \seq_gput_right:NV
+ \g__enumext_footnote_starred_int_seq \g__enumext_footnote_starred_int
+ }
+ }
+\cs_new_protected:Nn \__enumext_print_footnote_mini:
+ {
+ \seq_if_empty:NF \g__enumext_footnote_starred_int_seq
+ {
+ \seq_map_pairwise_function:NNN
+ \g__enumext_footnote_starred_int_seq
+ \g__enumext_footnote_starred_arg_seq
+ \__enumext_footnotetext:nn
+ }
+ \seq_gclear:N \g__enumext_footnote_starred_arg_seq
+ \seq_gclear:N \g__enumext_footnote_starred_int_seq
+ }
+\cs_new_protected:Nn \__enumext_renew_footnote_standar:
+ {
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \IfDocumentMetadataTF
+ {
+ \__enumext_renew_footnote:
+ }
+ {
+ \bool_if:NF \l__enumext_footnotes_key_bool
+ {
+ \__enumext_renew_footnote:
+ }
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_print_footnote_standar:
+ {
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \IfDocumentMetadataTF
+ {
+ \__enumext_print_footnote:
+ }
+ {
+ \bool_if:NF \l__enumext_footnotes_key_bool
+ {
+ \__enumext_print_footnote:
+ }
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_renew_footnote_starred:
+ {
+ \IfDocumentMetadataTF
+ {
+ \__enumext_renew_footnote_mini:
+ }
+ {
+ \bool_if:NF \l__enumext_footnotes_key_bool
+ {
+ \__enumext_renew_footnote_mini:
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_print_footnote_starred:
+ {
+ \IfDocumentMetadataTF
+ {
+ \__enumext_print_footnote_mini:
+ }
+ {
+ \bool_if:NF \l__enumext_footnotes_key_bool
+ {
+ \__enumext_print_footnote_mini:
+ }
+ }
+ }
+\__enumext_after_env:nn { enumext* }
+ {
+ \__enumext_print_footnote_starred:
+ }
+\__enumext_after_env:nn { keyans* }
+ {
+ \__enumext_print_footnote_starred:
+ }
+%% Function for define a internal |minipage| environment with |\footnote| support.
+\cs_new_protected:Nn \__enumext_internal_mini_page:
+ {
+ \int_compare:nNnT { \l__enumext_level_int } = { 0 }
+ {
+ \DeclareDocumentEnvironment{__enumext_mini_page}{ m }
+ {
+ \__enumext_renew_footnote_standar:
+ \__enumext_minipage:w [ t ] { ##1 }
+ \legacy_if_gset_false:n { @minipage }
+ \skip_vertical:N \c_zero_skip
+ }
+ {
+ \skip_vertical:N \c_zero_skip
+ \__enumext_endminipage:
+ \__enumext_print_footnote_standar:
+ }
+ }
+ }
+%% Public dimension |\itemwidth|
+\dim_zero_new:N \itemwidth
+%% Definition of counters.
+\cs_new_protected:Npn \__enumext_define_counters:Nn #1 #2
+ {
+ \cs_if_exist:cTF { c@ #2 }
+ { \msg_fatal:nnn { enumext } { counters }{ #2 } }
+ {
+ \tl_set:Nn #1 { #2 }
+ \newcounter { #2 }
+ }
+ }
+\__enumext_define_counters:Nn \l__enumext_counter_i_tl { enumXi }
+\__enumext_define_counters:Nn \l__enumext_counter_ii_tl { enumXii }
+\__enumext_define_counters:Nn \l__enumext_counter_iii_tl { enumXiii }
+\__enumext_define_counters:Nn \l__enumext_counter_iv_tl { enumXiv }
+\__enumext_define_counters:Nn \l__enumext_counter_v_tl { enumXv }
+\__enumext_define_counters:Nn \l__enumext_counter_vi_tl { enumXvi }
+\__enumext_define_counters:Nn \l__enumext_counter_vii_tl { enumXvii }
+\__enumext_define_counters:Nn \l__enumext_counter_viii_tl { enumXviii }
+%% Register of counters style.
+\cs_new_protected:Npn \__enumext_register_counter_style:Nn #1 #2
+ {
+ \tl_const:cn { c__enumext_widest_ \cs_to_str:N #1 _tl } {#2}
+ \tl_gput_right:Nn \g__enumext_counter_styles_tl {#1}
+ }
+\__enumext_register_counter_style:Nn \arabic { 0 }
+\__enumext_register_counter_style:Nn \Alph { M }
+\__enumext_register_counter_style:Nn \alph { m }
+\__enumext_register_counter_style:Nn \Roman { VIII }
+\__enumext_register_counter_style:Nn \roman { viii }
+%% Set default label width using a box width.
+\cs_new_protected:Npn \__enumext_label_width_by_box:Nn #1 #2
+ {
+ \hbox_set:Nn \l__enumext_label_width_by_box {#2}
+ \dim_set:Nn #1 { \box_wd:N \l__enumext_label_width_by_box }
+ }
+\cs_generate_variant:Nn \__enumext_label_width_by_box:Nn { cv }
+%% Function to support |*| in |label| key.
+\cs_new_protected:Npn \__enumext_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__enumext_widest_label_tl #1
+ \tl_map_inline:Nn \g__enumext_counter_styles_tl
+ {
+ \tl_replace_all:Nne #1 { ##1* } { \exp_not:N ##1 {#2} }
+ \tl_greplace_all:Nne \g__enumext_widest_label_tl { ##1* }
+ { \tl_use:c { c__enumext_widest_ \cs_to_str:N ##1 _tl } }
+ }
+ \__enumext_label_width_by_box:Nn \l__enumext_current_widest_dim
+ { \tl_use:N \g__enumext_widest_label_tl }
+ \tl_set_eq:cN { the #2 } #1
+ }
+\cs_generate_variant:Nn \__enumext_label_style:Nnn { cvn }
+%% Add |mode-box| key only on first level off |enumext| and |enumext*| environments.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ mode-box .bool_set:N = \l__enumext_mode_box_bool,
+ mode-box .initial:n = false,
+ mode-box .value_forbidden:n = true,
+ }
+ }
+\clist_map_inline:nn { level-1, enumext* } { \__enumext_tmp:n {#1} }
+%% Add |font|, |labelsep|, |labelwidth|, |wrap-label| and |wrap-label*| keys.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ font .tl_set:c = { l__enumext_label_font_style_#2_tl },
+ font .value_required:n = true,
+ labelsep .dim_set:c = { l__enumext_labelsep_#2_dim },
+ labelsep .initial:n = {0.3333em},
+ labelsep .value_required:n = true,
+ labelwidth .dim_set:c = { l__enumext_labelwidth_#2_dim },
+ labelwidth .value_required:n = true,
+ wrap-label .cs_set_protected:cp = { __enumext_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__enumext_wrap_label_opt_#2_bool }
+ \keys_set:nn { enumext / #1 } { wrap-label = {##1} }
+ },
+ wrap-label* .value_required:n = true,
+ }
+ }
+\clist_map_inline:Nn \c__enumext_all_envs_clist { \__enumext_tmp:nn #1 }
+%% Add |align| key for |enumext| and |keyans| environments.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ align .choice:,
+ align / left .code:n =
+ {
+ \tl_clear:c { l__enumext_label_fill_left_#2_tl }
+ \tl_set:cn { l__enumext_label_fill_right_#2_tl } { \hfill }
+ \str_set:cn { l__enumext_align_label_pos_#2_str } { l }
+ },
+ align / right .code:n =
+ {
+ \tl_set:cn { l__enumext_label_fill_left_#2_tl } { \hfill }
+ \tl_clear:c { l__enumext_label_fill_right_#2_tl }
+ \str_set:cn { l__enumext_align_label_pos_#2_str } { r }
+ },
+ align / center .code:n =
+ {
+ \tl_set:cn { l__enumext_label_fill_left_#2_tl } { \hfill }
+ \tl_set:cn { l__enumext_label_fill_right_#2_tl } { \hfill }
+ \str_set:cn { l__enumext_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}
+ }
+ { \__enumext_tmp:nn #1 }
+%% Add |align| key for |enummext*| and |keyans*| environments.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ align .choice:,
+ align / left .code:n = \str_set:cn { l__enumext_align_label_#2_str } { l },
+ align / right .code:n = \str_set:cn { l__enumext_align_label_#2_str } { r },
+ align / center .code:n = \str_set:cn { l__enumext_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} } { \__enumext_tmp:nn #1 }
+%% Define and set |label| and |ref| keys for |enumext|.
+\cs_set_protected:Npn \__enumext_tmp:nnn #1 #2 #3
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ label .code:n = {
+ \__enumext_label_style:cvn { l__enumext_label_#2_tl }
+ { l__enumext_counter_#2_tl } {##1}
+ \dim_set_eq:cN { l__enumext_labelwidth_#2_dim }
+ \l__enumext_current_widest_dim
+ },
+ label .initial:n = #3,
+ label .value_required:n = true,
+ ref .code:n = \__enumext_standar_ref:n {##1},
+ ref .value_required:n = true,
+ }
+ }
+\__enumext_tmp:nnn { level-1 } { i } { \arabic*.}
+\__enumext_tmp:nnn { level-2 } { ii } { (\alph*) }
+\__enumext_tmp:nnn { level-3 } { iii } { \roman*. }
+\__enumext_tmp:nnn { level-4 } { iv } { \Alph*. }
+%% Internal function used by |ref| key in enumext environment.
+\cs_new_protected:Npn \__enumext_standar_ref:n #1
+ {
+ \tl_set:Nn \l__enumext_ref_key_arg_tl {#1}
+ \tl_if_empty:NTF \l__enumext_ref_key_arg_tl
+ {
+ \msg_error:nnn { enumext } { key-ref-empty } { enumext }
+ }
+ {
+ \tl_set_eq:Nc
+ \l__enumext_ref_the_count_tl { l__enumext_counter_ \__enumext_level: _tl }
+ \__enumext_regex_counter_style:
+ \tl_set_eq:Nc
+ \l__enumext_ref_the_count_tl { l__enumext_the_counter_ \__enumext_level: _tl }
+ \tl_put_right:ce { l__enumext_renew_the_count_ \__enumext_level: _tl }
+ {
+ \exp_not:N \renewcommand { \exp_not:V \l__enumext_ref_the_count_tl } { \exp_not:V \l__enumext_ref_key_arg_tl }
+ }
+ }
+ }
+%% Activate |ref| key in second arg of list for |enumext| environment.
+\cs_new_protected:Nn \__enumext_standar_ref:
+ {
+ \tl_if_empty:cF { l__enumext_renew_the_count_ \__enumext_level: _tl }
+ {
+ \tl_use:c { l__enumext_renew_the_count_ \__enumext_level: _tl }
+ }
+ }
+%% Define and set |label| and |ref| keys for starred environments.
+\cs_set_protected:Npn \__enumext_tmp:nnn #1 #2 #3
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ label .code:n = {
+ \__enumext_label_style:cvn { l__enumext_label_#2_tl }
+ { l__enumext_counter_#2_tl } {##1}
+ \dim_set_eq:cN { l__enumext_labelwidth_#2_dim }
+ \l__enumext_current_widest_dim
+ },
+ label .initial:n = #3,
+ label .value_required:n = true,
+ ref .code:n = \__enumext_starred_ref:n {##1},
+ ref .value_required:n = true,
+ }
+ }
+\__enumext_tmp:nnn { enumext* } { vii } { \arabic*.}
+\__enumext_tmp:nnn { keyans* } { viii } { \Alph*) }
+%% Internal function used by |ref| key in |enumext*| and |keyans*| environments.
+\cs_new_protected:Npn \__enumext_starred_ref:n #1
+ {
+ \tl_set:Nn \l__enumext_ref_key_arg_tl {#1}
+ \int_compare:nNnT { \l__enumext_level_h_int } = { 1 }
+ {
+ \tl_if_empty:NTF \l__enumext_ref_key_arg_tl
+ {
+ \msg_error:nnn { enumext } { key-ref-empty } { enumext* }
+ }
+ {
+ \tl_set_eq:NN \l__enumext_ref_the_count_tl \l__enumext_counter_vii_tl
+ \__enumext_regex_counter_style:
+ \tl_set_eq:NN \l__enumext_ref_the_count_tl \l__enumext_the_counter_vii_tl
+ \tl_put_right:Ne \l__enumext_renew_the_count_vii_tl
+ {
+ \exp_not:N \renewcommand { \exp_not:V \l__enumext_ref_the_count_tl } { \exp_not:V \l__enumext_ref_key_arg_tl }
+ }
+ }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_h_int } = { 1 }
+ {
+ \tl_if_empty:NTF \l__enumext_ref_key_arg_tl
+ {
+ \msg_error:nnn { enumext } { key-ref-empty } { keyans* }
+ }
+ {
+ \tl_set_eq:NN \l__enumext_ref_the_count_tl \l__enumext_counter_viii_tl
+ \__enumext_regex_counter_style:
+ \tl_set_eq:NN \l__enumext_ref_the_count_tl \l__enumext_the_counter_viii_tl
+ \tl_put_right:Ne \l__enumext_renew_the_count_viii_tl
+ {
+ \exp_not:N \renewcommand { \exp_not:V \l__enumext_ref_the_count_tl } { \exp_not:V \l__enumext_ref_key_arg_tl }
+ }
+ }
+ }
+ }
+%% Activate |ref| key in second arg of list for |enumext*| and |keyans*| environments.
+\cs_new_protected:Nn \__enumext_starred_ref:
+ {
+ \int_compare:nNnT { \l__enumext_level_h_int } = { 1 }
+ {
+ \tl_if_empty:NF \l__enumext_renew_the_count_vii_tl
+ {
+ \tl_use:N \l__enumext_renew_the_count_vii_tl
+ }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_h_int } = { 1 }
+ {
+ \tl_if_empty:NF \l__enumext_renew_the_count_viii_tl
+ {
+ \tl_use:N \l__enumext_renew_the_count_viii_tl
+ }
+ }
+ }
+%% Define and set |label| and |ref| keys for |keyans| and |keyanspic|.
+\keys_define:nn { enumext / keyans }
+ {
+ label .code:n = {
+ \__enumext_label_style:cvn { l__enumext_label_v_tl }
+ { l__enumext_counter_v_tl } {#1}
+ \dim_set_eq:cN { l__enumext_labelwidth_v_dim }
+ \l__enumext_current_widest_dim
+ \__enumext_label_style:cvn { l__enumext_label_vi_tl }
+ { l__enumext_counter_vi_tl } {#1}
+ \dim_set_eq:cN { l__enumext_labelwidth_v_dim }
+ \l__enumext_current_widest_dim
+ },
+ label .initial:n = \Alph*),
+ label .value_required:n = true,
+ ref .code:n = \__enumext_keyans_ref:n {#1},
+ ref .value_required:n = true,
+ }
+%% Internal function used by |ref| key in |keyans| environment.
+\cs_new_protected:Npn \__enumext_keyans_ref:n #1
+ {
+ \tl_set:Nn \l__enumext_ref_key_arg_tl {#1}
+ \tl_if_empty:NTF \l__enumext_ref_key_arg_tl
+ {
+ \msg_error:nnn { enumext } { key-ref-empty } { keyans }
+ }
+ {
+ \tl_set_eq:NN \l__enumext_ref_the_count_tl \l__enumext_counter_v_tl
+ \__enumext_regex_counter_style:
+ \tl_set_eq:NN \l__enumext_ref_the_count_tl \l__enumext_the_counter_v_tl
+ \tl_put_right:Ne \l__enumext_renew_the_count_v_tl
+ {
+ \exp_not:N \renewcommand { \exp_not:V \l__enumext_ref_the_count_tl } { \exp_not:V \l__enumext_ref_key_arg_tl }
+ }
+ }
+ }
+%% Activate |ref| key in second arg of list for |keyans| environments.
+\cs_new_protected:Nn \__enumext_keyans_ref:
+ {
+ \tl_if_empty:NF \l__enumext_renew_the_count_v_tl
+ {
+ \tl_use:N \l__enumext_renew_the_count_v_tl
+ }
+ }
+%% Internal function for |start| key.
+%% #1 \l_enumext_label_X_tl
+%% #2 \l_enumext_start_X_int
+%% #3 integer or string
+\cs_new_protected:Npn \__enumext_start_from:NNn #1 #2 #3
+ {
+ \__enumext_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 \__enumext_start_from:NNn { ccn, cce }
+%% 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
+\cs_new_protected:Npn \__enumext_widest_from:nNNn #1 #2 #3 #4
+ {
+ \__enumext_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} } }
+ }
+ \__enumext_label_width_by_box:cv
+ { l__enumext_labelwidth_#1_dim } { l__enumext_label_#1_tl }
+ }
+\cs_generate_variant:Nn \__enumext_widest_from:nNNn { nccn }
+%% Add |start*|, |start| and |widest| key.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ start* .code:n = {
+ \__enumext_start_from:ccn
+ { l__enumext_label_#2_tl }
+ { l__enumext_start_#2_int } {##1}
+ },
+ start* .value_required:n = true,
+ start .code:n = {
+ \__enumext_start_from:cce
+ { l__enumext_label_#2_tl }
+ { l__enumext_start_#2_int } { \int_eval:n {##1} }
+ },
+ start .initial:n = 1,
+ start .value_required:n = true,
+ widest .code:n = {
+ \__enumext_widest_from:nccn {#2}
+ { l__enumext_label_#2_tl }
+ { l__enumext_labelwidth_#2_dim } {##1}
+ },
+ widest .value_required:n = true,
+ }
+ }
+\clist_map_inline:Nn \c__enumext_all_envs_clist { \__enumext_tmp:nn #1 }
+%% Add |topsep|, |partopsep|, |parsep|, |noitemsep| and |nosep| keys.
+\cs_set_protected:Npn \__enumext_tmp:nnnnnn #1 #2 #3 #4 #5 #6
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ topsep .skip_set:c = { l__enumext_topsep_#2_skip },
+ topsep .initial:n = {#3},
+ topsep .value_required:n = true,
+ partopsep .skip_set:c = { l__enumext_partopsep_#2_skip },
+ partopsep .initial:n = {#4},
+ partopsep .value_required:n = true,
+ parsep .skip_set:c = { l__enumext_parsep_#2_skip },
+ parsep .initial:n = {#5},
+ parsep .value_required:n = true,
+ itemsep .skip_set:c = { l__enumext_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,
+ }
+ }
+\__enumext_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 }
+\__enumext_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 }
+\__enumext_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 }
+\__enumext_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 }
+\__enumext_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 }
+\__enumext_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 }
+\__enumext_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 }
+%% Add |base-fix| key only on first level off |enumext| environment.
+\keys_define:nn { enumext / level-1 }
+ {
+ base-fix .bool_set:N = \l__enumext_base_line_fix_bool,
+ base-fix .initial:n = false,
+ base-fix .value_forbidden:n = true,
+ }
+%% Internal function for |base-fix| key in |enumext| environment.
+\cs_new_protected:Nn \__enumext_nested_base_line_fix:
+ {
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \l__enumext_starred_first_bool }
+ { \bool_if_p:N \l__enumext_base_line_fix_bool }
+ { \bool_not_p:n { \l__enumext_print_keyans_star_bool } }
+ }
+ {
+ \mode_leave_vertical:
+ \vspace { -\dim_eval:n { \baselineskip + \parsep } }
+ }
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_starred_first_bool }
+ { \bool_if_p:N \l__enumext_print_keyans_star_bool }
+ {
+ \mode_leave_vertical:
+ \skip_vertical:n { -\baselineskip }
+ \skip_vertical:N \c_zero_skip
+ }
+ \keys_set:nn { enumext / level-1 }
+ {
+ topsep = 0pt, above = 0pt, above* = 0pt,
+ }
+ \bool_set_false:N \l__enumext_base_line_fix_bool
+ }
+%% Add |itemindent|, |rightmargin|, |listparindent|, |list-offset| and |list-indent| keys.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ itemindent .dim_set:c = { l__enumext_fake_item_indent_#2_dim },
+ itemindent .value_required:n = true,
+ rightmargin .dim_set:c = { l__enumext_rightmargin_#2_dim },
+ rightmargin .value_required:n = true,
+ listparindent .dim_set:c = { l__enumext_listparindent_#2_dim },
+ listparindent .value_required:n = true,
+ list-offset .dim_set:c = { l__enumext_listoffset_#2_dim },
+ list-offset .value_required:n = true,
+ list-indent .code:n =
+ \bool_set_true:c { l__enumext_leftmargin_tmp_#2_bool }
+ \dim_set:cn { l__enumext_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}
+ }
+ { \__enumext_tmp:nn #1 }
+%% Set |list-offset| and |list-indent| keys for |enumext*| and |keyans*| environments.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ itemindent .dim_set:c = { l__enumext_fake_item_indent_#2_dim },
+ itemindent .value_required:n = true,
+ rightmargin .dim_set:c = { l__enumext_rightmargin_#2_dim },
+ rightmargin .value_required:n = true,
+ listparindent .dim_set:c = { l__enumext_listparindent_#2_dim },
+ listparindent .value_required:n = true,
+ list-offset .dim_set:c = { l__enumext_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}
+ }
+ { \__enumext_tmp:nn #1 }
+%% Internal functions for |itemindent| key. |\mode_leave_vertical:| nor
+\cs_set_protected:Nn \__enumext_fake_item_indent:
+ {
+ \dim_compare:nNnT
+ { \dim_use:c { l__enumext_fake_item_indent_ \__enumext_level: _dim } }
+ >
+ { \c_zero_dim }
+ {
+ \tl_set:ce { l__enumext_fake_item_indent_ \__enumext_level: _tl }
+ {
+ \exp_not:N \mode_leave_vertical:
+ \exp_not:n { \skip_horizontal:n }
+ { \dim_use:c { l__enumext_fake_item_indent_ \__enumext_level: _dim } }
+ \exp_not:N \ignorespaces
+ }
+ }
+ }
+\cs_set_protected:Nn \__enumext_keyans_fake_item_indent:
+ {
+ \dim_compare:nNnT
+ { \l__enumext_fake_item_indent_v_dim } > { \c_zero_dim }
+ {
+ \tl_set:Ne \l__enumext_fake_item_indent_v_tl
+ {
+ \exp_not:N \mode_leave_vertical:
+ \exp_not:N \skip_horizontal:N \l__enumext_fake_item_indent_v_dim
+ \exp_not:N \ignorespaces
+ }
+ }
+ }
+\cs_set_protected:Nn \__enumext_fake_item_indent_vii:
+ {
+ \dim_compare:nNnT
+ { \l__enumext_fake_item_indent_vii_dim } > { \c_zero_dim }
+ {
+ \tl_set:Ne \l__enumext_fake_item_indent_vii_tl
+ {
+ \exp_not:N \skip_horizontal:N \l__enumext_fake_item_indent_vii_dim
+ \exp_not:N \ignorespaces
+ }
+ }
+ }
+\cs_set_protected:Nn \__enumext_fake_item_indent_viii:
+ {
+ \dim_compare:nNnT
+ { \l__enumext_fake_item_indent_viii_dim } > { \c_zero_dim }
+ {
+ \tl_set:Ne \l__enumext_fake_item_indent_viii_tl
+ {
+ \exp_not:N \skip_horizontal:N \l__enumext_fake_item_indent_viii_dim
+ \exp_not:N \ignorespaces
+ }
+ }
+ }
+%% Add |show-length| key for all environments..
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ show-length .bool_set:c = { l__enumext_show_length_#2_bool },
+ show-length .initial:n = false,
+ }
+ }
+\clist_map_inline:Nn \c__enumext_all_envs_clist { \__enumext_tmp:nn #1 }
+%% Add |before|, |before*|, |after| and |first| keys.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ before .tl_set:c = { l__enumext_before_no_starred_key_#2_tl },
+ before .value_required:n = true,
+ before* .tl_set:c = { l__enumext_before_starred_key_#2_tl },
+ before* .value_required:n = true,
+ after .tl_set:c = { l__enumext_after_stop_list_#2_tl },
+ after .value_required:n = true,
+ first .tl_set:c = { l__enumext_after_list_args_#2_tl },
+ first .value_required:n = true,
+ }
+ }
+\clist_map_inline:Nn \c__enumext_all_envs_clist { \__enumext_tmp:nn #1 }
+%% Function for |before|, |before*|, |after| and |first| keys in |enumext|.
+\cs_new_protected:Nn \__enumext_before_args_exec:
+ {
+ \tl_use:c { l__enumext_before_starred_key_ \__enumext_level: _tl }
+ }
+\cs_new_protected:Nn \__enumext_before_keys_exec:
+ {
+ \tl_use:c { l__enumext_before_no_starred_key_ \__enumext_level: _tl }
+ }
+\cs_new_protected:Nn \__enumext_after_stop_list:
+ {
+ \tl_use:c { l__enumext_after_stop_list_ \__enumext_level: _tl }
+ }
+\cs_new_protected:Nn \__enumext_after_args_exec:
+ {
+ \tl_use:c { l__enumext_after_list_args_ \__enumext_level: _tl }
+ }
+%% Function for |before|, |before*|, |after| and |first| keys in |keyans|.
+\cs_new_protected:Nn \__enumext_before_args_exec_v:
+ {
+ \tl_use:N \l__enumext_before_starred_key_v_tl
+ }
+\cs_new_protected:Nn \__enumext_before_keys_exec_v:
+ {
+ \tl_use:N \l__enumext_before_no_starred_key_v_tl
+ }
+\cs_new_protected:Nn \__enumext_after_stop_list_v:
+ {
+ \tl_use:N \l__enumext_after_stop_list_v_tl
+ }
+\cs_new_protected:Nn \__enumext_after_args_exec_v:
+ {
+ \tl_use:N \l__enumext_after_list_args_v_tl
+ }
+%% Function for |before|, |before*|, |after| and |first| keys in |enumext*| and |keyans*|.
+\cs_new_protected:Nn \__enumext_before_args_exec_vii:
+ {
+ \tl_use:N \l__enumext_before_starred_key_vii_tl
+ }
+\cs_new_protected:Nn \__enumext_before_args_exec_viii:
+ {
+ \tl_use:N \l__enumext_before_starred_key_viii_tl
+ }
+\cs_new_protected:Nn \__enumext_before_keys_exec_vii:
+ {
+ \tl_use:N \l__enumext_before_no_starred_key_vii_tl
+ }
+\cs_new_protected:Nn \__enumext_before_keys_exec_viii:
+ {
+ \tl_use:N \l__enumext_before_no_starred_key_viii_tl
+ }
+\cs_new_protected:Nn \__enumext_after_stop_list_vii:
+ {
+ \tl_use:N \l__enumext_after_stop_list_vii_tl
+ }
+\cs_new_protected:Nn \__enumext_after_stop_list_viii:
+ {
+ \tl_use:N \l__enumext_after_stop_list_viii_tl
+ }
+\cs_new_protected:Nn \__enumext_after_args_exec_vii:
+ {
+ \tl_use:N \l__enumext_after_list_args_vii_tl
+ }
+\cs_new_protected:Nn \__enumext_after_args_exec_viii:
+ {
+ \tl_use:N \l__enumext_after_list_args_viii_tl
+ }
+%% Add |mini-env|, |mini-sep|, |columns-sep| and |columns| keys.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ mini-env .dim_set:c = { l__enumext_minipage_right_#2_dim },
+ mini-env .value_required:n = true,
+ mini-sep .dim_set:c = { l__enumext_minipage_hsep_#2_dim },
+ mini-sep .initial:n = 0.3333em,
+ mini-sep .value_required:n = true,
+ columns-sep .dim_set:c = { l__enumext_columns_sep_#2_dim },
+ columns-sep .value_required:n = true,
+ columns .int_set:c = { l__enumext_columns_#2_int },
+ columns .initial:n = 1,
+ columns .value_required:n = true,
+ }
+ }
+\clist_map_inline:Nn \c__enumext_all_envs_clist { \__enumext_tmp:nn #1 }
+%% Add |mini-right| and |mini-right*| keys for starred environments.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ mini-right .tl_gset:c = { g__enumext_miniright_code_#2_tl },
+ mini-right .value_required:n = true,
+ mini-right* .code:n = {
+ \bool_gset_true:c { g__enumext_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} } { \__enumext_tmp:nn #1 }
+%% Adjustment of vertical spacing for |multicols| in |enumext|.
+\cs_new_protected:Nn \__enumext_multi_set_vskip:
+ {
+ \skip_set:cn { l__enumext_multicols_above_ \__enumext_level: _skip }
+ {
+ \skip_use:c { l__enumext_topsep_ \__enumext_level: _skip }
+ }
+ \skip_set:cn { l__enumext_multicols_below_ \__enumext_level: _skip }
+ {
+ \skip_use:c { l__enumext_topsep_ \__enumext_level: _skip }
+ }
+ \__enumext_add_pre_parsep:
+ }
+%% Detect |\parsep| from previous level and adjust |\l_@@_multicols_above_X_skip| for |multicols| in |enumext|.
+\cs_new_protected:Nn \__enumext_add_pre_parsep:
+ {
+ \int_case:nn { \l__enumext_level_int }
+ {
+ { 2 }{
+ \skip_if_eq:nnF { \l__enumext_parsep_i_skip } { \c_zero_skip }
+ {
+ \skip_add:Nn \l__enumext_multicols_above_ii_skip
+ {
+ \l__enumext_parsep_i_skip
+ }
+ }
+ }
+ { 3 }{
+ \skip_if_eq:nnF { \l__enumext_parsep_ii_skip } { \c_zero_skip }
+ {
+ \skip_add:Nn \l__enumext_multicols_above_iii_skip
+ {
+ \l__enumext_parsep_ii_skip
+ }
+ }
+ }
+ { 4 }{
+ \skip_if_eq:nnF { \l__enumext_parsep_iii_skip } { \c_zero_skip }
+ {
+ \skip_add:Nn \l__enumext_multicols_above_iv_skip
+ {
+ \l__enumext_parsep_iii_skip
+ }
+ }
+ }
+ }
+ }
+%% Add vertical spacing for |multicols| in |enumext| environment.
+\cs_new_protected:Nn \__enumext_multi_addvspace:
+ {
+ \__enumext_multi_set_vskip:
+ \mode_if_vertical:T
+ {
+ \skip_add:cn { l__enumext_multicols_above_ \__enumext_level: _skip }
+ {
+ \skip_use:c { l__enumext_partopsep_ \__enumext_level: _skip }
+ }
+ \skip_add:cn { l__enumext_multicols_below_ \__enumext_level: _skip }
+ {
+ \skip_use:c { l__enumext_partopsep_ \__enumext_level: _skip }
+ }
+ }
+ \par\nopagebreak
+ \addvspace{ \skip_use:c { l__enumext_multicols_above_ \__enumext_level: _skip } }
+ }
+%% Adjustment of vertical spacing for |multicols| in |keyans| environments.
+\cs_new_protected:Nn \__enumext_keyans_multi_set_vskip:
+ {
+ \skip_set:Nn \l__enumext_multicols_above_v_skip
+ {
+ \l__enumext_topsep_v_skip
+ }
+ \skip_set:Nn \l__enumext_multicols_below_v_skip
+ {
+ \l__enumext_topsep_v_skip
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_multi_addvspace:
+ {
+ \__enumext_keyans_multi_set_vskip:
+ \mode_if_vertical:T
+ {
+ \skip_add:Nn \l__enumext_multicols_above_v_skip
+ {
+ \skip_use:N \l__enumext_partopsep_v_skip
+ }
+ \skip_add:Nn \l__enumext_multicols_below_v_skip
+ {
+ \skip_use:N \l__enumext_partopsep_v_skip
+ }
+ }
+ \par\nopagebreak
+ \addvspace{ \l__enumext_multicols_above_v_skip }
+ }
+%% Adjustment of vertical spacing for |minipage| in |enumext| environment.
+\cs_new_protected:Nn \__enumext_minipage_set_skip:
+ {
+ \skip_set:Nn \l__enumext_minipage_right_skip
+ {
+ \skip_use:c { l__enumext_topsep_ \__enumext_level: _skip }
+ }
+ \mode_if_vertical:T
+ {
+ \skip_add:Nn \l__enumext_minipage_right_skip
+ {
+ \skip_use:c { l__enumext_partopsep_ \__enumext_level: _skip }
+ }
+ }
+ \skip_set_eq:NN \l__enumext_minipage_after_skip \l__enumext_minipage_right_skip
+ \skip_set_eq:cN
+ { l__enumext_multicols_above_ \__enumext_level: _skip } \l__enumext_minipage_right_skip
+ \skip_set_eq:cN
+ { l__enumext_multicols_below_ \__enumext_level: _skip } \l__enumext_minipage_right_skip
+ \__enumext_pre_itemsep_skip:
+ \int_compare:nNnT
+ { \int_use:c { l__enumext_columns_ \__enumext_level: _int } } > { 1 }
+ {
+ \skip_zero:N \topskip
+ \skip_set_eq:Nc \multicolsep { l__enumext_multicols_above_ \__enumext_level: _skip }
+ }
+ }
+\cs_new_protected:Nn \__enumext_minipage_add_space:
+ {
+ \__enumext_minipage_set_skip:
+ \__enumext_unskip_unkern:
+ \mode_if_vertical:TF
+ {
+ \nopagebreak\nointerlineskip
+ }
+ {
+ \par\nopagebreak\nointerlineskip
+ \skip_zero:c { l__enumext_partopsep_ \__enumext_level: _skip }
+ }
+ \int_compare:nNnTF
+ { \int_use:c { l__enumext_columns_ \__enumext_level: _int } } > { 1 }
+ {
+ \addvspace{ 0.445\box_ht:N \strutbox }
+ }
+ {
+ \addvspace{ 0.250\box_ht:N \strutbox }
+ }
+ }
+\cs_new_protected:Nn \__enumext_pre_itemsep_skip:
+ {
+ \int_case:nn { \l__enumext_level_int }
+ {
+ { 2 }{
+ \skip_if_eq:nnTF
+ { \l__enumext_itemsep_i_skip } { \l__enumext_minipage_after_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_set:Nn \l__enumext_multicols_below_ii_skip { 0.350\box_ht:N \strutbox }
+ }
+ {
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_i_skip } < { \l__enumext_minipage_after_skip }
+ {
+ \skip_sub:Nn
+ \l__enumext_minipage_after_skip { \l__enumext_itemsep_i_skip }
+ \skip_sub:Nn
+ \l__enumext_multicols_below_ii_skip { \l__enumext_itemsep_i_skip }
+ \skip_add:Nn
+ \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_add:Nn
+ \l__enumext_multicols_below_ii_skip { 0.350\box_ht:N \strutbox }
+ }
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_i_skip } > { \l__enumext_minipage_after_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_temp_skip
+ {
+ \l__enumext_itemsep_i_skip - \l__enumext_minipage_after_skip
+ }
+ \skip_sub:Nn
+ \l__enumext_minipage_after_skip { \l__enumext_itemsep_i_skip }
+ \skip_sub:Nn
+ \l__enumext_multicols_below_ii_skip { \l__enumext_itemsep_i_skip }
+ \skip_add:Nn
+ \l__enumext_minipage_after_skip
+ { 0.150\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ \skip_add:Nn
+ \l__enumext_multicols_below_ii_skip
+ { 0.350\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ }
+ }
+ }
+ { 3 }{
+ \skip_if_eq:nnTF
+ { \l__enumext_itemsep_ii_skip } { \c_zero_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_set:Nn \l__enumext_multicols_below_iii_skip { 0.350\box_ht:N \strutbox }
+ }
+ {
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_ii_skip } < { \l__enumext_minipage_after_skip }
+ {
+ \skip_sub:Nn
+ \l__enumext_minipage_after_skip { \l__enumext_itemsep_ii_skip }
+ \skip_sub:Nn
+ \l__enumext_multicols_below_iii_skip { \l__enumext_itemsep_ii_skip }
+ \skip_add:Nn
+ \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_add:Nn
+ \l__enumext_multicols_below_iii_skip { 0.350\box_ht:N \strutbox }
+ }
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_ii_skip } > { \l__enumext_minipage_after_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_temp_skip
+ {
+ \l__enumext_itemsep_ii_skip - \l__enumext_minipage_after_skip
+ }
+ \skip_sub:Nn
+ \l__enumext_minipage_after_skip { \l__enumext_itemsep_ii_skip }
+ \skip_sub:Nn
+ \l__enumext_multicols_below_iii_skip { \l__enumext_itemsep_ii_skip }
+ \skip_add:Nn
+ \l__enumext_minipage_after_skip
+ { 0.150\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ \skip_add:Nn
+ \l__enumext_multicols_below_iii_skip
+ { 0.350\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ }
+ }
+ }
+ { 4 }{
+ \skip_if_eq:nnTF { \l__enumext_itemsep_iii_skip } { \c_zero_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_set:Nn \l__enumext_multicols_below_iv_skip { 0.350\box_ht:N \strutbox }
+ }
+ {
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_iii_skip } < { \l__enumext_minipage_after_skip }
+ {
+ \skip_sub:Nn
+ \l__enumext_minipage_after_skip { \l__enumext_itemsep_iii_skip }
+ \skip_sub:Nn
+ \l__enumext_multicols_below_iv_skip { \l__enumext_itemsep_iii_skip }
+ \skip_add:Nn
+ \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_add:Nn
+ \l__enumext_multicols_below_iv_skip { 0.350\box_ht:N \strutbox }
+ }
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_iii_skip } > { \l__enumext_minipage_after_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_temp_skip
+ {
+ \l__enumext_itemsep_iii_skip - \l__enumext_minipage_after_skip
+ }
+ \skip_sub:Nn
+ \l__enumext_minipage_after_skip { \l__enumext_itemsep_iii_skip }
+ \skip_sub:Nn
+ \l__enumext_multicols_below_iv_skip { \l__enumext_itemsep_iii_skip }
+ \skip_add:Nn
+ \l__enumext_minipage_after_skip
+ { 0.150\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ \skip_add:Nn
+ \l__enumext_multicols_below_iv_skip
+ { 0.350\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ }
+ }
+ }
+ }
+ }
+%% Adjustment of vertical spacing for |minipage| in |keyans| environments.
+\cs_new_protected:Nn \__enumext_keyans_minipage_set_skip:
+ {
+ \skip_zero:N \l__enumext_minipage_after_skip
+ \skip_zero:N \l__enumext_minipage_left_skip
+ \skip_zero:N \l__enumext_minipage_right_skip
+ \skip_set:Nn \l__enumext_minipage_right_skip
+ {
+ \l__enumext_topsep_v_skip
+ }
+ \mode_if_vertical:T
+ {
+ \skip_add:Nn \l__enumext_minipage_right_skip
+ {
+ \l__enumext_partopsep_v_skip
+ }
+ }
+ \skip_set_eq:NN \l__enumext_minipage_after_skip \l__enumext_minipage_right_skip
+ \skip_set_eq:NN \l__enumext_multicols_above_v_skip \l__enumext_minipage_right_skip
+ \skip_set_eq:NN \l__enumext_multicols_below_v_skip \l__enumext_minipage_right_skip
+ \__enumext_keyans_pre_itemsep_skip:
+ \int_compare:nNnT { \l__enumext_columns_v_int } > { 1 }
+ {
+ \skip_zero:N \topskip
+ \skip_set_eq:NN \multicolsep \l__enumext_minipage_right_skip
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_minipage_add_space:
+ {
+ \__enumext_keyans_minipage_set_skip:
+ \__enumext_unskip_unkern:
+ \mode_if_vertical:TF
+ {
+ \nopagebreak\nointerlineskip
+ }
+ {
+ \par\nopagebreak\nointerlineskip
+ \skip_zero:N \l__enumext_partopsep_v_skip
+ }
+ \int_compare:nNnTF { \l__enumext_columns_v_int } > { 1 }
+ {
+ \addvspace{ 0.445\box_ht:N \strutbox }
+ }
+ {
+ \addvspace{ 0.250\box_ht:N \strutbox }
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_pre_itemsep_skip:
+ {
+ \skip_if_eq:nnTF
+ { \l__enumext_itemsep_i_skip } { \l__enumext_minipage_after_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_set:Nn \l__enumext_multicols_below_v_skip { 0.350\box_ht:N \strutbox }
+ }
+ {
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_i_skip } < { \l__enumext_minipage_after_skip }
+ {
+ \skip_sub:Nn \l__enumext_minipage_after_skip { \l__enumext_itemsep_i_skip }
+ \skip_sub:Nn \l__enumext_multicols_below_v_skip { \l__enumext_itemsep_i_skip }
+ \skip_add:Nn \l__enumext_minipage_after_skip { 0.150\box_ht:N \strutbox }
+ \skip_add:Nn \l__enumext_multicols_below_v_skip { 0.350\box_ht:N \strutbox }
+ }
+ \dim_compare:nNnT
+ { \l__enumext_itemsep_i_skip } > { \l__enumext_minipage_after_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_temp_skip
+ {
+ \l__enumext_itemsep_i_skip - \l__enumext_minipage_after_skip
+ }
+ \skip_sub:Nn \l__enumext_minipage_after_skip { \l__enumext_itemsep_i_skip }
+ \skip_sub:Nn \l__enumext_multicols_below_v_skip { \l__enumext_itemsep_i_skip }
+ \skip_add:Nn \l__enumext_minipage_after_skip
+ { 0.150\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ \skip_add:Nn \l__enumext_multicols_below_v_skip
+ { 0.350\box_ht:N \strutbox + \l__enumext_minipage_temp_skip }
+ }
+ }
+ }
+%% Adjustment of vertical spacing for |minipage| in |enumext*| and |keyans*|.
+\cs_new_protected:Nn \__enumext_mini_set_vskip_vii:
+ {
+ \skip_zero_new:N \l__enumext_minipage_left_skip
+ \skip_gzero_new:N \g__enumext_minipage_right_skip
+ \skip_gzero_new:N \g__enumext_minipage_after_skip
+ \skip_if_eq:nnTF { \l__enumext_topsep_vii_skip } { \c_zero_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_left_skip { 0.5\box_dp:N \strutbox }
+ \skip_gset:Nn \g__enumext_minipage_right_skip { 0.325\box_dp:N \strutbox }
+ }
+ {
+ \skip_set:Nn \l__enumext_minipage_left_skip { 0.5875\box_dp:N \strutbox }
+ \skip_gset:Nn \g__enumext_minipage_right_skip
+ {
+ \l__enumext_topsep_vii_skip
+ }
+ \skip_gset:Nn \g__enumext_minipage_after_skip
+ {
+ 0.325\box_dp:N \strutbox + \l__enumext_topsep_vii_skip
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_mini_set_vskip_viii:
+ {
+ \skip_zero_new:N \l__enumext_minipage_after_skip
+ \skip_zero_new:N \l__enumext_minipage_left_skip
+ \skip_zero_new:N \l__enumext_minipage_right_skip
+ \skip_if_eq:nnTF { \l__enumext_topsep_viii_skip } { \c_zero_skip }
+ {
+ \skip_set:Nn \l__enumext_minipage_left_skip
+ {
+ 0.5\box_dp:N \strutbox
+ }
+ \skip_set:Nn \l__enumext_minipage_right_skip
+ {
+ \l__enumext_partopsep_viii_skip
+ }
+ \skip_set:Nn \l__enumext_minipage_after_skip
+ {
+ 1.6\box_dp:N \strutbox
+ }
+ }
+ {
+ \skip_set:Nn \l__enumext_minipage_left_skip
+ {
+ 0.5875\box_dp:N \strutbox
+ }
+ \skip_set:Nn \l__enumext_minipage_right_skip
+ {
+ \l__enumext_topsep_viii_skip
+ }
+ \skip_set:Nn \l__enumext_minipage_after_skip
+ {
+ 0.325\box_dp:N \strutbox + \l__enumext_topsep_viii_skip
+ }
+ }
+ }
+%% Apply \addvspace above minipage for |enumext*| and |keyans*| environments.
+\cs_new_protected:Nn \__enumext_mini_addvspace_vii:
+ {
+ \__enumext_mini_set_vskip_vii:
+ \par\nopagebreak
+ \addvspace { \l__enumext_minipage_left_skip }
+ }
+\cs_new_protected:Nn \__enumext_mini_addvspace_viii:
+ {
+ \__enumext_mini_set_vskip_viii:
+ \par\nopagebreak
+ \addvspace { \l__enumext_minipage_left_skip }
+ }
+%% Definition of |\miniright| command.
+\NewDocumentCommand \miniright { s }
+ {
+ \int_compare:nNnT { \l__enumext_keyans_pic_level_int } = { 1 }
+ {
+ \msg_error:nnn { enumext } { wrong-miniright-place }
+ }
+ % outside
+ \bool_lazy_and:nnT
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 0 } }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 0 } }
+ {
+ \msg_error:nnn { enumext } { wrong-miniright-place }
+ }
+ % starred env
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \g__enumext_starred_bool }
+ { \bool_not_p:n { \l__enumext_standar_bool } }
+ {
+ \msg_error:nnn { enumext } { wrong-miniright-starred }
+ }
+ % exec
+ \int_compare:nNnTF { \l__enumext_keyans_level_int } = { 1 }
+ {
+ \__enumext_keyans_mini_right_cmd:n {#1}
+ }
+ { \__enumext_mini_right_cmd:n {#1} }
+ }
+%% Internal function for |\miniright| command in enumext.
+\cs_new_protected:Npn \__enumext_mini_right_cmd:n #1
+ {
+ \dim_compare:nNnTF
+ { \dim_use:c { l__enumext_minipage_right_ \__enumext_level: _dim } } > { \c_zero_dim }
+ {
+ \__enumext_multicols_stop:
+ \int_compare:nNnT
+ { \int_use:c { l__enumext_columns_ \__enumext_level: _int } } = { 1 }
+ {
+ \par\addvspace{ \l__enumext_minipage_after_skip }
+ }
+ \end__enumext_mini_page
+ \hfill
+ \__enumext_mini_page{ \dim_use:c { l__enumext_minipage_right_ \__enumext_level: _dim } }
+ \par\nointerlineskip
+ \addvspace { \l__enumext_minipage_right_skip }
+ \bool_if:nF {#1}
+ {
+ \centering
+ }
+ \int_gzero:N \g__enumext_minipage_stat_int
+ }
+ { \msg_error:nnn { enumext } { wrong-miniright-use } }
+ % paranoia
+ \RenewDocumentCommand \miniright { s }
+ {
+ \msg_error:nn { enumext } { many-miniright-used }
+ }
+ }
+%% Internal function for |\miniright| command in keyans.
+\cs_new_protected:Npn \__enumext_keyans_mini_right_cmd:n #1
+ {
+ \dim_compare:nNnTF { \l__enumext_minipage_right_v_dim } > { \c_zero_dim }
+ {
+ \__enumext_keyans_multicols_stop:
+ \int_compare:nNnT { \l__enumext_columns_v_int } = { 1 }
+ {
+ \par\addvspace{ \l__enumext_minipage_after_skip }
+ }
+ \end__enumext_mini_page
+ \hfill
+ \__enumext_mini_page{ \l__enumext_minipage_right_v_dim }
+ \par\nointerlineskip
+ \addvspace { \l__enumext_minipage_right_skip }
+ \bool_if:nF {#1}
+ {
+ \centering
+ }
+ \int_gzero:N \g__enumext_minipage_stat_int
+ }
+ { \msg_error:nnn { enumext } { wrong-miniright-use } }
+ % paranoia
+ \RenewDocumentCommand \miniright { s }
+ {
+ \msg_error:nn { enumext } { many-miniright-used }
+ }
+ }
+%% Add |above| and |below| keys.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ above .skip_set:c = { l__enumext_vspace_above_#2_skip },
+ above .value_required:n = true,
+ above* .code:n = \bool_set_true:c { l__enumext_vspace_a_star_#2_bool }
+ \keys_set:nn { enumext / #1 } { above = {##1} },
+ above* .value_required:n = true,
+ below .skip_set:c = { l__enumext_vspace_below_#2_skip },
+ below .value_required:n = true,
+ below* .code:n = \bool_set_true:c { l__enumext_vspace_b_star_#2_bool }
+ \keys_set:nn { enumext / #1 } { below = {##1} },
+ below* .value_required:n = true,
+ }
+ }
+\clist_map_inline:Nn \c__enumext_all_envs_clist { \__enumext_tmp:nn #1 }
+%% Function for |above|, |above*|, |below| and |below*| keys in |enumext|.
+\cs_new_protected:Nn \__enumext_vspace_above:
+ {
+ \skip_if_eq:nnF
+ { \skip_use:c { l__enumext_vspace_above_ \__enumext_level: _skip } } { \c_zero_skip }
+ {
+ \bool_if:cTF { l__enumext_vspace_a_star_ \__enumext_level: _bool }
+ {
+ \vspace*{ \skip_use:c { l__enumext_vspace_above_ \__enumext_level: _skip } }
+ }
+ {
+ \vspace { \skip_use:c { l__enumext_vspace_above_ \__enumext_level: _skip } }
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_vspace_below:
+ {
+ \skip_if_eq:nnF
+ { \skip_use:c { l__enumext_vspace_below_ \__enumext_level: _skip } } { \c_zero_skip }
+ {
+ \bool_if:cTF { l__enumext_vspace_b_star_ \__enumext_level: _bool }
+ {
+ \vspace*{ \skip_use:c { l__enumext_vspace_below_ \__enumext_level: _skip } }
+ }
+ {
+ \vspace { \skip_use:c { l__enumext_vspace_below_ \__enumext_level: _skip } }
+ }
+ }
+ }
+%% Function for |above|, |above*|, |below| and |below*| keys in |keyans|.
+\cs_new_protected:Nn \__enumext_vspace_above_v:
+ {
+ \skip_if_eq:nnF { \l__enumext_vspace_above_v_skip } { \c_zero_skip }
+ {
+ \bool_if:NTF \l__enumext_vspace_a_star_v_bool
+ {
+ \vspace*{ \l__enumext_vspace_above_v_skip }
+ }
+ { \vspace { \l__enumext_vspace_above_v_skip } }
+ }
+ }
+\cs_new_protected:Nn \__enumext_vspace_below_v:
+ {
+ \skip_if_eq:nnF { \l__enumext_vspace_below_v_skip } { \c_zero_skip }
+ {
+ \bool_if:NTF \l__enumext_vspace_b_star_v_bool
+ {
+ \vspace*{ \l__enumext_vspace_below_v_skip }
+ }
+ { \vspace { \l__enumext_vspace_below_v_skip } }
+ }
+ }
+%% Function for |above|, |above*|, |below| and |below*| keys in |enumext*| and |keyans*|.
+\cs_new_protected:Nn \__enumext_vspace_above_vii:
+ {
+ \skip_if_eq:nnF { \l__enumext_vspace_above_vii_skip } { \c_zero_skip }
+ {
+ \bool_if:NTF \l__enumext_vspace_a_star_vii_bool
+ {
+ \vspace*{ \l__enumext_vspace_above_vii_skip }
+ }
+ { \vspace { \l__enumext_vspace_above_vii_skip } }
+ }
+ }
+\cs_new_protected:Nn \__enumext_vspace_above_viii:
+ {
+ \skip_if_eq:nnF { \l__enumext_vspace_above_viii_skip } { \c_zero_skip }
+ {
+ \bool_if:NTF \l__enumext_vspace_a_star_viii_bool
+ {
+ \vspace*{ \l__enumext_vspace_above_viii_skip }
+ }
+ { \vspace { \l__enumext_vspace_above_viii_skip } }
+ }
+ }
+\cs_new_protected:Nn \__enumext_vspace_below_vii:
+ {
+ \skip_if_eq:nnF { \l__enumext_vspace_below_vii_skip } { \c_zero_skip }
+ {
+ \bool_if:NTF \l__enumext_vspace_b_star_vii_bool
+ {
+ \vspace*{ \l__enumext_vspace_below_vii_skip }
+ }
+ { \vspace { \l__enumext_vspace_below_vii_skip } }
+ }
+ }
+\cs_new_protected:Nn \__enumext_vspace_below_viii:
+ {
+ \skip_if_eq:nnF { \l__enumext_vspace_below_viii_skip } { \c_zero_skip }
+ {
+ \bool_if:NTF \l__enumext_vspace_b_star_viii_bool
+ {
+ \vspace*{ \l__enumext_vspace_below_viii_skip }
+ }
+ { \vspace { \l__enumext_vspace_below_viii_skip } }
+ }
+ }
+%% Add |series|, |resume| and |resume*| keys only on first level off |enumext| and |enumext*|.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ series .str_set:N = \l__enumext_series_str,
+ series .value_required:n = true,
+ resume .code:n = \__enumext_resume_series:n {##1},
+ resume* .code:n = \__enumext_resume_starred:,
+ resume* .value_forbidden:n = true,
+ }
+ }
+\clist_map_inline:nn { level-1, enumext* } { \__enumext_tmp:n {#1} }
+%% Internal function for filter keys.
+\cs_new:Npn \__enumext_filter_series:n #1
+ {
+ \use:e
+ {
+ \keyval_parse:NNn
+ \__enumext_filter_series_key:n
+ \__enumext_filter_series_pair:nn {#1}
+ }
+ }
+\cs_new:Npn \__enumext_filter_series_key:n #1
+ {
+ \str_case:nnF {#1}
+ {
+ { resume } {} { resume* } {} { base-fix } {}
+ }
+ { , { \exp_not:n {#1} } }
+ }
+\cs_new:Npn \__enumext_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} } }
+ }
+%% Internal function for parse filter keys used by |series|, |resume| and |resume*| keys.
+\cs_new_protected:Npn \__enumext_parse_series:n #1
+ {
+ \str_if_empty:NTF \l__enumext_series_str
+ {
+ \bool_if:NF \l__enumext_resume_active_bool
+ {
+ \__enumext_resume_last:n {#1}
+ }
+ }
+ {
+ \tl_gclear_new:c { g__enumext_series_ \l__enumext_series_str _tl }
+ \tl_gset:ce { g__enumext_series_ \l__enumext_series_str _tl }
+ { \__enumext_filter_series:n {#1} }
+ \int_if_exist:cF { g__enumext_series_ \l__enumext_series_str _int }
+ {
+ \int_new:c { g__enumext_series_ \l__enumext_series_str _int }
+ }
+ }
+ }
+%% Save keys for last environment without |series|, |resume| and |resume*| keys active.
+\cs_new_protected:Npn \__enumext_resume_last:n #1
+ {
+ \bool_if:NT \l__enumext_standar_first_bool
+ {
+ \tl_gclear:N \g__enumext_standar_series_tl
+ \tl_gset:Ne \g__enumext_standar_series_tl { \__enumext_filter_series:n {#1} }
+ }
+ \bool_if:NT \l__enumext_starred_first_bool
+ {
+ \tl_gclear:N \g__enumext_starred_series_tl
+ \tl_gset:Ne \g__enumext_starred_series_tl { \__enumext_filter_series:n {#1} }
+ }
+ }
+%% Internal function to save counter value and set int vars for |series|, |resume| and |resume*| keys.
+\cs_new_protected:Nn \__enumext_resume_save_counter:
+ {
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \tl_if_empty:NF \l__enumext_series_str
+ {
+ \int_gset_eq:cN
+ { g__enumext_series_ \l__enumext_series_str _int } \value{enumXi}
+ }
+ \tl_if_empty:NTF \l__enumext_resume_name_tl
+ {
+ \str_if_empty:NT \l__enumext_series_str
+ {
+ \int_gset_eq:NN \g__enumext_resume_int \value{enumXi}
+ }
+ }
+ {
+ \int_if_exist:cT { g__enumext_series_ \l__enumext_resume_name_tl _int }
+ {
+ \int_gset_eq:cN
+ { g__enumext_series_ \l__enumext_resume_name_tl _int } \value{enumXi}
+ }
+ }
+ \int_if_exist:cT { g__enumext_resume_ \l__enumext_store_name_tl _int }
+ {
+ \int_gset_eq:cN
+ { g__enumext_resume_ \l__enumext_store_name_tl _int } \value{enumXi}
+ }
+ }
+ \bool_if:NT \g__enumext_starred_bool
+ {
+ \tl_if_empty:NF \l__enumext_series_str
+ {
+ \int_gset_eq:cN
+ { g__enumext_series_ \l__enumext_series_str _int } \value{enumXvii}
+ }
+ \tl_if_empty:NTF \l__enumext_resume_name_tl
+ {
+ \str_if_empty:NT \l__enumext_series_str
+ {
+ \int_gset_eq:NN \g__enumext_resume_vii_int \value{enumXvii}
+ }
+ }
+ {
+ \int_if_exist:cT { g__enumext_series_ \l__enumext_resume_name_tl _int }
+ {
+ \int_gset_eq:cN
+ { g__enumext_series_ \l__enumext_resume_name_tl _int } \value{enumXvii}
+ }
+ }
+ \int_if_exist:cT { g__enumext_resume_ \l__enumext_store_name_tl _int }
+ {
+ \int_gset_eq:cN
+ { g__enumext_resume_ \l__enumext_store_name_tl _int } \value{enumXvii}
+ }
+ }
+ }
+%% Internal function for |resume| key.
+\cs_new_protected:Npn \__enumext_resume_series:n #1
+ {
+ \tl_if_empty:nTF {#1}
+ {
+ \__enumext_resume_counter:n { }
+ }
+ {
+ \tl_if_exist:cTF { g__enumext_series_ \tl_to_str:n {#1} _tl }
+ {
+ \__enumext_resume_counter:n {#1}
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \keys_set:nv { enumext / level-1 }
+ { g__enumext_series_ \tl_to_str:n {#1} _tl }
+ }
+ \bool_if:NT \g__enumext_starred_bool
+ {
+ \keys_set:nv { enumext / enumext* }
+ { g__enumext_series_ \tl_to_str:n {#1} _tl }
+ }
+ }
+ {
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \msg_error:nnn { enumext } { unknown-series } {#1}
+ }
+ \bool_if:NT \g__enumext_starred_bool
+ {
+ \msg_error:nnn { enumext } { unknown-series } {#1}
+ }
+ }
+ }
+ }
+\cs_new_protected:Npn \__enumext_resume_counter:n #1
+ {
+ \bool_set_true:N \l__enumext_resume_active_bool
+ \tl_set:Nn \l__enumext_resume_name_tl {#1}
+ \tl_if_empty:NTF \l__enumext_resume_name_tl
+ {
+ \__enumext_resume_counter:
+ }
+ {
+ \__enumext_resume_counter_series:
+ }
+ \__enumext_resume_counter_save_ans:
+ }
+\cs_new_protected:Nn \__enumext_resume_counter:
+ {
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \int_gincr:N \g__enumext_resume_int
+ \int_set_eq:NN \l__enumext_start_i_int \g__enumext_resume_int
+ }
+ \bool_if:NT \g__enumext_starred_bool
+ {
+ \int_gincr:N \g__enumext_resume_vii_int
+ \int_set_eq:NN \l__enumext_start_vii_int \g__enumext_resume_vii_int
+ }
+ }
+\cs_new_protected:Nn \__enumext_resume_counter_series:
+ {
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \int_set:Nn \l__enumext_start_i_int
+ {
+ \int_use:c { g__enumext_series_ \l__enumext_resume_name_tl _int } + 1
+ }
+ }
+ \bool_if:NT \g__enumext_starred_bool
+ {
+ \int_set:Nn \l__enumext_start_vii_int
+ {
+ \int_use:c { g__enumext_series_ \l__enumext_resume_name_tl _int } + 1
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_resume_counter_save_ans:
+ {
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_standar_first_bool }
+ { \bool_if_p:N \l__enumext_store_active_bool }
+ {
+ \int_set:Nn \l__enumext_start_i_int
+ {
+ \int_use:c { g__enumext_resume_ \l__enumext_store_name_tl _int } + 1
+ }
+ }
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_starred_first_bool }
+ { \bool_if_p:N \l__enumext_store_active_bool }
+ {
+ \int_set:Nn \l__enumext_start_vii_int
+ {
+ \int_use:c { g__enumext_resume_ \l__enumext_store_name_tl _int } + 1
+ }
+ }
+ }
+%% Internal function for |resume*| key.
+\cs_new_protected:Nn \__enumext_resume_starred:
+ {
+ \bool_if:NT \g__enumext_standar_bool
+ {
+ \tl_if_empty:NF \g__enumext_standar_series_tl
+ {
+ \__enumext_resume_counter:n { }
+ \keys_set:nV { enumext / level-1 } \g__enumext_standar_series_tl
+ }
+ }
+ \bool_if:NT \g__enumext_starred_bool
+ {
+ \tl_if_empty:NF \g__enumext_starred_series_tl
+ {
+ \__enumext_resume_counter:n { }
+ \keys_set:nV { enumext / enumext* } \g__enumext_starred_series_tl
+ }
+ }
+ }
+%% Add |save-ans| key only on first level off |enumext| and |enumext*|.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ save-ans .code:n = \__enumext_storing_set:n {##1},
+ save-ans .value_required:n = true,
+ }
+ }
+\clist_map_inline:nn { level-1, enumext* } { \__enumext_tmp:n {#1} }
+%% Print/write start and stop environment with |save-ans| key active.
+\cs_new_protected:Nn \__enumext_start_save_ans_msg:
+ {
+ \msg_term:nnVV { enumext } { save-ans-log }
+ \g__enumext_envir_name_tl \l__enumext_store_name_tl
+ }
+\cs_new_protected:Nn \__enumext_stop_save_ans_msg:
+ {
+ \msg_term:nnVV { enumext } { save-ans-log-hook }
+ \g__enumext_envir_name_tl \g__enumext_store_name_tl
+ }
+%% Function to activate ALL "storing" (and |check-ans|, |no-store|, |resume|, |anskey*|) used by |save-ans| key.
+\cs_new_protected:Npn \__enumext_storing_set:n #1
+ {
+ \tl_set:Ne \l__enumext_store_name_tl {#1}
+ \tl_if_empty:NTF \l__enumext_store_name_tl
+ {
+ \bool_lazy_or:nnT
+ { \l__enumext_standar_first_bool } { \l__enumext_starred_first_bool }
+ {
+ \msg_error:nnV { enumext } { save-ans-empty } \g__enumext_envir_name_tl
+ }
+ }
+ {
+ \bool_lazy_or:nnT
+ { \l__enumext_standar_first_bool } { \l__enumext_starred_first_bool }
+ {
+ \__enumext_start_save_ans_msg:
+ \__enumext_storing_exec:
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_storing_exec:
+ {
+ \bool_set_true:N \l__enumext_store_active_bool
+ \bool_set_true:N \l__enumext_check_answers_bool
+ \tl_gset:NV \g__enumext_store_name_tl \l__enumext_store_name_tl
+ \__enumext_anskey_env_make:V \l__enumext_store_name_tl
+ \prop_if_exist:cF { g__enumext_ \l__enumext_store_name_tl _prop }
+ {
+ \msg_log:nnV { enumext } { store-prop } \l__enumext_store_name_tl
+ \prop_new:c { g__enumext_ \l__enumext_store_name_tl _prop }
+ }
+ \seq_if_exist:cF { g__enumext_ \l__enumext_store_name_tl _seq }
+ {
+ \msg_log:nnV { enumext } { store-seq } \l__enumext_store_name_tl
+ \seq_new:c { g__enumext_ \l__enumext_store_name_tl _seq }
+ }
+ \int_if_exist:cF { g__enumext_resume_ \l__enumext_store_name_tl _int }
+ {
+ \msg_log:nnV { enumext } { store-int } \l__enumext_store_name_tl
+ \int_new:c { g__enumext_resume_ \l__enumext_store_name_tl _int }
+ }
+ }
+%% Add |check-ans| and |no-store| keys.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ check-ans .bool_set:N = \l__enumext_check_ans_key_bool,
+ check-ans .initial:n = false,
+ check-ans .value_required:n = true,
+ no-store .code:n = {
+ \bool_set_false:N \l__enumext_check_answers_bool
+ \bool_set_false:N \l__enumext_check_ans_key_bool
+ },
+ no-store .value_forbidden:n = true,
+ }
+ }
+\clist_map_inline:nn
+ {
+ level-1, level-2, level-3, level-4, enumext*
+ }
+ { \__enumext_tmp:n {#1} }
+%% Internal function for checking answer mechanism in |enumext| and |enumext*| environments.
+\cs_new_protected:Nn \__enumext_check_ans_active:
+ {
+ \tl_if_empty:NF \l__enumext_store_name_tl
+ {
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \__enumext_check_ans_level:
+ }
+ }
+ }
+%% Decrementing \g_@@_item_number_int for nested level.
+\cs_new_protected:Nn \__enumext_check_ans_level:
+ {
+ \int_case:nn { \l__enumext_level_int }
+ {
+ { 1 }{
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \g__enumext_starred_bool }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 1 } }
+ }
+ {
+ \int_gdecr:N \g__enumext_item_number_int
+ \bool_set_false:N \l__enumext_item_number_bool
+ }
+ }
+ { 2 }{
+ \int_gdecr:N \g__enumext_item_number_int
+ \bool_set_false:N \l__enumext_item_number_bool
+ }
+ { 3 }{
+ \int_gdecr:N \g__enumext_item_number_int
+ \bool_set_false:N \l__enumext_item_number_bool
+ }
+ { 4 }{
+ \int_gdecr:N \g__enumext_item_number_int
+ \bool_set_false:N \l__enumext_item_number_bool
+ }
+ }
+ \int_case:nn { \l__enumext_level_h_int }
+ {
+ { 1 }{
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \g__enumext_standar_bool }
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 1 } }
+ }
+ {
+ \int_gdecr:N \g__enumext_item_number_int
+ \bool_set_false:N \l__enumext_item_number_bool
+ }
+ }
+ }
+ }
+%% Function to export \l_@@_check_ans_key_bool for |check-ans| key.
+\cs_new_protected:Nn \__enumext_check_ans_key_hook:
+ {
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_check_ans_key_bool }
+ { \bool_if_p:N \g__enumext_standar_bool }
+ {
+ \bool_gset_true:N \g__enumext_check_ans_key_bool
+ }
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_check_ans_key_bool }
+ { \bool_if_p:N \g__enumext_starred_bool }
+ {
+ \bool_gset_true:N \g__enumext_check_ans_key_bool
+ }
+ }
+%% Set \g_@@_item_answer_diff_int for |check-ans| key and internal.
+\cs_new_protected:Nn \__enumext_item_answer_diff:
+ {
+ \int_gset:Nn \g__enumext_item_answer_diff_int
+ {
+ \int_sign:n { \g__enumext_item_number_int - \g__enumext_item_anskey_int }
+ }
+ }
+%% Function to print |check-ans| key.
+\cs_new_protected:Nn \__enumext_check_ans_show:
+ {
+ \int_case:nn { \g__enumext_item_answer_diff_int }
+ {
+ { -1 }{ \__enumext_check_ans_msg_less: }
+ { 0 }{ \__enumext_check_ans_msg_same_ok: }
+ { 1 }{ \__enumext_check_ans_msg_greater: }
+ }
+ }
+\cs_new_protected:Nn \__enumext_check_ans_msg_less:
+ {
+ \msg_warning:nneee { enumext } { item-less-answer } { \g__enumext_store_name_tl }
+ { \g__enumext_envir_name_tl } { \g__enumext_start_line_tl }
+ }
+\cs_new_protected:Nn \__enumext_check_ans_msg_same_ok:
+ {
+ \msg_term:nneee { enumext } { items-same-answer } { \g__enumext_store_name_tl }
+ { \g__enumext_envir_name_tl } { \g__enumext_start_line_tl }
+ }
+\cs_new_protected:Nn \__enumext_check_ans_msg_greater:
+ {
+ \msg_warning:nneee { enumext } { item-greater-answer } { \g__enumext_store_name_tl }
+ { \g__enumext_envir_name_tl } { \g__enumext_start_line_tl }
+ }
+%% Function to log check-answer mechanisms.
+\cs_new_protected:Nn \__enumext_check_ans_log:
+ {
+ \int_case:nn { \g__enumext_item_answer_diff_int }
+ {
+ { -1 }{ \__enumext_check_ans_log_msg_less: }
+ { 0 }{ \__enumext_check_ans_log_msg_same_ok: }
+ { 1 }{ \__enumext_check_ans_log_msg_greater: }
+ }
+ }
+\cs_new_protected:Nn \__enumext_check_ans_log_msg_less:
+ {
+ \msg_log:nneee { enumext } { item-less-answer } { \g__enumext_store_name_tl }
+ { \g__enumext_envir_name_tl } { \g__enumext_start_line_tl }
+ }
+\cs_new_protected:Nn \__enumext_check_ans_log_msg_same_ok:
+ {
+ \msg_log:nneee { enumext } { items-same-answer } { \g__enumext_store_name_tl }
+ { \g__enumext_envir_name_tl } { \g__enumext_start_line_tl }
+ }
+\cs_new_protected:Nn \__enumext_check_ans_log_msg_greater:
+ {
+ \msg_log:nneee { enumext } { item-greater-answer } { \g__enumext_store_name_tl }
+ { \g__enumext_envir_name_tl } { \g__enumext_start_line_tl }
+ }
+%% Function for check |\item*| and |\anspic*| commands.
+\cs_new_protected:Npn \__enumext_check_starred_cmd:n #1
+ {
+ \int_compare:nNnT
+ { \g__enumext_check_starred_cmd_int } = { 0 }
+ {
+ \msg_warning:nnnV
+ { enumext } { missing-starred }{ #1 } \l__enumext_check_start_line_env_tl
+ }
+ \int_compare:nNnT
+ { \g__enumext_check_starred_cmd_int } > { 1 }
+ {
+ \msg_warning:nnnV
+ { enumext } { many-starred }{ #1 } \l__enumext_check_start_line_env_tl
+ }
+ \int_gzero:N \g__enumext_check_starred_cmd_int
+ \tl_clear:N \l__enumext_check_start_line_env_tl
+ }
+%% Add keys associated with storage on first level of |enumext| and |enumext*|.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ wrap-ans .cs_set_protected:Np = \__enumext_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 = \__enumext_keyans_wrapper_opt:n ##1,
+ wrap-opt .initial:n = [{##1}],
+ wrap-opt .value_required:n = true,
+ save-sep .tl_set:N = \l__enumext_store_keyans_item_opt_sep_tl,
+ save-sep .initial:n = {, ~ },
+ save-sep .value_required:n = true,
+ mark-ans .tl_set:N = \l__enumext_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__enumext_mark_position_str { l },
+ mark-pos / right .code:n = \str_set:Nn \l__enumext_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__enumext_show_answer_bool,
+ show-ans .initial:n = false,
+ show-ans .value_required:n = true,
+ show-pos .bool_set:N = \l__enumext_show_position_bool,
+ show-pos .initial:n = false,
+ show-pos .value_required:n = true,
+ mark-ref .tl_set:N = \l__enumext_mark_ref_sym_tl,
+ mark-ref .initial:n = \textreferencemark,
+ mark-ref .value_required:n = true,
+ save-ref .bool_set:N = \l__enumext_store_ref_key_bool,
+ save-ref .initial:n = false,
+ save-ref .value_required:n = true,
+ }
+ }
+\clist_map_inline:nn { level-1, enumext* } { \__enumext_tmp:n {#1} }
+%% Add keys |mark-pos|, |show-pos| and |show-ans| keys for |keyans| and |keyans*| environments.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ mark-pos .choice:,
+ mark-pos / left .code:n = \str_set:Nn \l__enumext_mark_position_str { l },
+ mark-pos / right .code:n = \str_set:Nn \l__enumext_mark_position_str { r },
+ mark-pos .initial:n = right,
+ mark-pos .value_required:n = true,
+ show-ans .bool_set:N = \l__enumext_show_answer_bool,
+ show-ans .initial:n = false,
+ show-ans .value_required:n = true,
+ show-pos .bool_set:N = \l__enumext_show_position_bool,
+ show-pos .initial:n = false,
+ show-pos .value_required:n = true,
+ }
+ }
+\clist_map_inline:nn { keyans, keyans* } { \__enumext_tmp:n {#1} }
+%% Internal function for store optional arguments of the environments in seq.
+\cs_new_protected:Npn \__enumext_store_active_keys:n #1
+ {
+ \bool_if:cF { l__enumext_store_save_key_ \__enumext_level: _bool }
+ {
+ \tl_clear:c { l__enumext_save_key_ \__enumext_level: _tl }
+ \tl_set:ce
+ { l__enumext_store_save_key_ \__enumext_level: _tl }
+ { \__enumext_filter_save_key:n {#1} }
+ }
+ }
+\cs_new_protected:Npn \__enumext_store_active_keys_vii:n #1
+ {
+ \bool_if:NF \l__enumext_store_save_key_vii_bool
+ {
+ \tl_clear:N \l__enumext_store_save_key_vii_tl
+ \tl_set:Ne \l__enumext_store_save_key_vii_tl { \__enumext_filter_save_key:n {#1} }
+ }
+ }
+%% Add |save-key| key for |enumext| and |enumext*| environments.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / enumext* }
+ {
+ save-key .code:n = \__enumext_parse_save_key_vii:n {##1},
+ save-key .value_required:n = true,
+ }
+ \keys_define:nn { enumext / #1 }
+ {
+ save-key .code:n = \__enumext_parse_save_key:n {##1},
+ save-key .value_required:n = true,
+ }
+ }
+\clist_map_inline:nn { level-1, level-2, level-3, level-4 } { \__enumext_tmp:n {#1} }
+%% Internal function for |save-key| key.
+\cs_new_protected:Npn \__enumext_parse_save_key:n #1
+ {
+ \bool_set_true:c { l__enumext_store_save_key_ \__enumext_level: _bool }
+ \tl_clear:c { l__enumext_save_key_ \__enumext_level: _tl }
+ \tl_set:ce
+ { l__enumext_store_save_key_ \__enumext_level: _tl }
+ { \__enumext_filter_save_key:n {#1} }
+ }
+\cs_new_protected:Npn \__enumext_parse_save_key_vii:n #1
+ {
+ \bool_set_true:N \l__enumext_store_save_key_vii_bool
+ \tl_clear:N \l__enumext_store_save_key_vii_tl
+ \tl_set:Ne \l__enumext_store_save_key_vii_tl { \__enumext_filter_save_key:n {#1} }
+ }
+%% Internal function for "filter keys" for |save-key| key.
+\cs_new:Npn \__enumext_filter_save_key:n #1
+ {
+ \use:e
+ {
+ \keyval_parse:NNn
+ \__enumext_filter_save_key_key:n
+ \__enumext_filter_save_key_pair:nn {#1}
+ }
+ }
+\cs_new:Npn \__enumext_filter_save_key_key:n #1
+ {
+ \str_case:nnF {#1}
+ {
+ { resume } {} { resume* } {} { no-store } {} { base-fix } {}
+ }
+ { , { \exp_not:n {#1} } }
+ }
+\cs_new:Npn \__enumext_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} } }
+ }
+%% Function for store content to prop list.
+\cs_new_protected:Npn \__enumext_store_addto_prop:n #1
+ {
+ \prop_gput_if_not_in:cen { g__enumext_ \l__enumext_store_name_tl _prop }
+ {
+ \int_eval:n { \prop_count:c { g__enumext_ \l__enumext_store_name_tl _prop } + 1 }
+ }
+ { #1 }
+ }
+\cs_generate_variant:Nn \__enumext_store_addto_prop:n { V }
+%% Function for store content to sequence.
+\cs_new_protected:Npn \__enumext_store_addto_seq:n #1
+ {
+ \seq_gput_right:cn { g__enumext_ \l__enumext_store_name_tl _seq } { #1 }
+ }
+\cs_generate_variant:Nn \__enumext_store_addto_seq:n { v, V }
+%% Function for storing structure level execution of |\anskey| on |enumext| environment.
+\cs_new_protected:Nn \__enumext_store_level_open:
+ {
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \tl_if_empty:cTF { l__enumext_store_save_key_ \__enumext_level: _tl }
+ {
+ \__enumext_store_addto_seq:n
+ {
+ \item \begin{enumext}
+ }
+ }
+ {
+ \tl_put_left:cn { l__enumext_store_save_key_ \__enumext_level: _tl }
+ {
+ \item \begin{enumext} [
+ }
+ \tl_put_right:cn { l__enumext_store_save_key_ \__enumext_level: _tl }
+ {
+ ]
+ }
+ \__enumext_store_addto_seq:v { l__enumext_store_save_key_ \__enumext_level: _tl }
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_store_level_close:
+ {
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \__enumext_store_addto_seq:n { \end{enumext} }
+ }
+ }
+%% Function storing structure level execution of |\anskey| and |anskey*| on |enumext*| environment.
+\cs_new_protected:Nn \__enumext_store_level_open_vii:
+ {
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \tl_if_empty:NTF \l__enumext_store_save_key_vii_tl
+ {
+ \__enumext_store_addto_seq:n
+ {
+ \item \begin{enumext*}
+ }
+ }
+ {
+ \tl_put_left:Nn \l__enumext_store_save_key_vii_tl
+ {
+ \item \begin{enumext*}[
+ }
+ \tl_put_right:Nn \l__enumext_store_save_key_vii_tl
+ {
+ ]
+ }
+ \__enumext_store_addto_seq:V \l__enumext_store_save_key_vii_tl
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_store_level_close_vii:
+ {
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \__enumext_store_addto_seq:n { \end{enumext*} }
+ }
+ }
+%% Function for put content in box on left margin.
+\cs_new_protected:Nn \__enumext_print_keyans_box:NN
+ {
+ \mode_leave_vertical:
+ \skip_horizontal:n { -\dim_use:N #2 }
+ \makebox[0pt][ r ]
+ {
+ \makebox[ \dim_use:N #1 ][ \l__enumext_mark_position_str ]
+ {
+ \tl_use:N \l__enumext_mark_answer_sym_tl
+ }
+ }
+ \skip_horizontal:n { \dim_use:N #2 }
+ }
+\cs_generate_variant:Nn \__enumext_print_keyans_box:NN { cc }
+%% Internal label and ref function for |\anskey| and |anskey*|.
+\cs_new_protected:Nn \__enumext_store_internal_ref:
+ {
+ \cs_set_protected:Npn \__enumext_tmp:n ##1
+ {
+ \tl_set_eq:cc { l__enumext_label_copy_##1_tl } { l__enumext_label_##1_tl }
+ \tl_reverse:c { l__enumext_label_copy_##1_tl }
+ \tl_remove_once:cn { l__enumext_label_copy_##1_tl } { . }
+ \tl_reverse:c { l__enumext_label_copy_##1_tl }
+ }
+ \clist_map_inline:nn { i, ii, iii, iv, vii } { \__enumext_tmp:n {##1} }
+ \cs_set:Npn \__enumext_tmp:n ##1
+ { . \tl_use:c { l__enumext_label_copy_ \int_to_roman:n {##1} _tl } }
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \g__enumext_starred_bool }
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 0 } }
+ }
+ {
+ \tl_put_right:Ne \l__enumext_newlabel_arg_two_tl
+ { \tl_use:N \l__enumext_label_copy_vii_tl }
+ }
+ \bool_lazy_all:nT
+ {
+ { \bool_not_p:n { \g__enumext_standar_bool } }
+ { \bool_if_p:N \l__enumext_standar_bool }
+ { \int_compare_p:nNn { \l__enumext_level_int } > { 0 } }
+ }
+ {
+ \tl_put_right:Ne \l__enumext_newlabel_arg_two_tl
+ {
+ \tl_use:N \l__enumext_label_copy_vii_tl
+ \int_step_function:nnN { 1 } { \l__enumext_level_int } \__enumext_tmp:n
+ }
+ }
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \g__enumext_standar_bool }
+ { \int_compare_p:nNn { \l__enumext_level_int } > { 0 } }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 0 } }
+ }
+ {
+ \tl_put_right:Ne \l__enumext_newlabel_arg_two_tl
+ {
+ \tl_use:N \l__enumext_label_copy_i_tl
+ \int_step_function:nnN { 2 } { \l__enumext_level_int } \__enumext_tmp:n
+ }
+ }
+ \cs_set:Npn \__enumext_tmp:n ##1
+ { \tl_use:c { l__enumext_label_copy_ \int_to_roman:n {##1} _tl } . }
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \g__enumext_standar_bool }
+ { \bool_if_p:N \l__enumext_starred_bool }
+ { \int_compare_p:nNn { \l__enumext_level_int } > { 0 } }
+ }
+ {
+ \tl_put_right:Ne \l__enumext_newlabel_arg_two_tl
+ {
+ \int_step_function:nnN { 1 } { \l__enumext_level_int } \__enumext_tmp:n
+ \tl_use:N \l__enumext_label_copy_vii_tl
+ }
+ }
+ \tl_put_right:Ne \l__enumext_newlabel_arg_one_tl
+ {
+ \l__enumext_store_name_tl \c_colon_str
+ \int_eval:n { \prop_count:c { g__enumext_ \l__enumext_store_name_tl _prop } }
+ }
+ \tl_put_right:Ne \l__enumext_write_aux_file_tl
+ {
+ \__enumext_newlabel:nn
+ { \exp_not:V \l__enumext_newlabel_arg_one_tl }
+ { \l__enumext_newlabel_arg_two_tl }
+ }
+ \l__enumext_write_aux_file_tl
+ }
+%% Internal function of |\anskey| for store content.
+\cs_new_protected:Npn \__enumext_store_anskey_code:n #1
+ {
+ \int_gincr:N \g__enumext_item_anskey_int
+ \__enumext_store_addto_prop:n {#1}
+ \bool_if:NT \l__enumext_store_ref_key_bool
+ {
+ \__enumext_store_internal_ref:
+ }
+ \__enumext_anskey_show_wrap_left:n { #1 }
+ \tl_clear:N \l__enumext_store_anskey_arg_tl
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_store_columns_break_bool }
+ { \bool_not_p:n { \l__enumext_starred_bool } }
+ {
+ \tl_put_left:Nn \l__enumext_store_anskey_arg_tl { \columnbreak }
+ }
+ \tl_put_right:Nn \l__enumext_store_anskey_arg_tl { \item }
+ \bool_lazy_and:nnT
+ { \bool_not_p:n { \l__enumext_starred_bool } }
+ { \int_compare_p:nNn { \l__enumext_store_item_join_int } > { 1 } }
+ {
+ \tl_put_right:Ne \l__enumext_store_anskey_arg_tl
+ {
+ ( \exp_not:V \l__enumext_store_item_join_int )
+ }
+ }
+ \bool_if:NTF \l__enumext_store_item_star_bool
+ {
+ \tl_put_right:Nn \l__enumext_store_anskey_arg_tl { * }
+ \tl_if_empty:NF \l__enumext_store_item_symbol_tl
+ {
+ \tl_put_right:Ne \l__enumext_store_anskey_arg_tl
+ {
+ [ \exp_not:V \l__enumext_store_item_symbol_tl ]
+ }
+ }
+ \dim_compare:nT
+ {
+ \l__enumext_store_item_symbol_sep_dim != \c_zero_dim
+ }
+ {
+ \tl_put_right:Ne \l__enumext_store_anskey_arg_tl
+ {
+ [ \exp_not:V \l__enumext_store_item_symbol_sep_dim ]
+ }
+ }
+ \tl_put_right:Nn \l__enumext_store_anskey_arg_tl {#1}
+ }
+ {
+ \tl_put_right:Nn \l__enumext_store_anskey_arg_tl {#1}
+ }
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_store_ref_key_bool }
+ { \bool_if_p:N \l__enumext_hyperref_bool }
+ {
+ \tl_put_right:Ne \l__enumext_store_anskey_arg_tl
+ {
+ \hfill \exp_not:N \hyperlink { \exp_not:V \l__enumext_newlabel_arg_one_tl }
+ { \exp_not:V \l__enumext_mark_ref_sym_tl }
+ }
+ }
+ \__enumext_store_addto_seq:V \l__enumext_store_anskey_arg_tl
+ }
+%% Internal |wrap-ans| implementation for |\anskey| and |anskey*|.
+\cs_new_protected:Npn \__enumext_anskey_show_wrap_arg:n #1
+ {
+ \par
+ \bool_if:NTF \l__enumext_starred_bool
+ {
+ \__enumext_print_keyans_box:NN
+ \l__enumext_labelwidth_vii_dim \l__enumext_labelsep_vii_dim
+ }
+ {
+ \__enumext_print_keyans_box:cc
+ { l__enumext_labelwidth_ \__enumext_level: _dim }
+ { l__enumext_labelsep_ \__enumext_level: _dim }
+ }
+ \__enumext_anskey_wrapper:n { #1 }
+ }
+%% Internal |show-ans| and |show-pos| implementation for |\anskey| and |anskey*|.
+\cs_new_protected:Npn \__enumext_anskey_show_wrap_left:n #1
+ {
+ \bool_if:NT \l__enumext_show_answer_bool
+ {
+ \__enumext_anskey_show_wrap_arg:n { #1 }
+ }
+ \bool_if:NT \l__enumext_show_position_bool
+ {
+ \tl_set:Ne \l__enumext_mark_answer_sym_tl
+ {
+ \group_begin:
+ \exp_not:N \normalfont
+ \exp_not:N \footnotesize [ \int_eval:n
+ {
+ \prop_count:c { g__enumext_ \l__enumext_store_name_tl _prop }
+ }
+ ]
+ \group_end:
+ }
+ \__enumext_anskey_show_wrap_arg:n { #1 }
+ }
+ }
+%% Add |key=val| for |\anskey|.
+\keys_define:nn { enumext / anskey }
+ {
+ break-col .bool_set:N = \l__enumext_store_columns_break_bool,
+ break-col .default:n = true,
+ break-col .value_forbidden:n = true,
+ item-join .int_set:N = \l__enumext_store_item_join_int,
+ item-join .value_required:n = true,
+ item-star .bool_set:N = \l__enumext_store_item_star_bool,
+ item-star .default:n = true,
+ item-star .value_forbidden:n = true,
+ item-sym* .tl_set:N = \l__enumext_store_item_symbol_tl,
+ item-sym* .value_required:n = true,
+ item-pos* .dim_set:N = \l__enumext_store_item_symbol_sep_dim,
+ item-pos* .value_required:n = true,
+ unknown .code:n = { \__enumext_anskey_unknown:n {#1} },
+ }
+\cs_new_protected:Npn \__enumext_anskey_unknown:n #1
+ {
+ \exp_args:NV \__enumext_anskey_unknown:nn \l_keys_key_str {#1}
+ }
+\cs_new_protected:Npn \__enumext_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}
+ }
+ }
+%% Define the user command |\anskey|.
+\NewDocumentCommand \anskey { o +m }
+ {
+ \__enumext_anskey_safe_outer:
+ \group_begin:
+ \bool_if:NT \l__enumext_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 }
+ }
+ {
+ \__enumext_anskey_safe_inner:
+ \__enumext_store_anskey_code:n {#2}
+ }
+ }
+ \group_end:
+ }
+%% Internal function for msg when |\anskey| is outer.
+\cs_new_protected:Nn \__enumext_anskey_safe_outer:
+ {
+ \bool_if:NF \l__enumext_store_active_bool
+ {
+ \msg_error:nnnn { enumext } { anskey-wrong-place }{ anskey }{ enumext }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_int } = { 1 }
+ {
+ \msg_error:nnnn { enumext } { command-wrong-place }{ anskey }{ keyans }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_h_int } = { 1 }
+ {
+ \msg_error:nnnn { enumext } { command-wrong-place }{ anskey }{ keyans* }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_pic_level_int } = { 1 }
+ {
+ \msg_error:nnnn { enumext } { command-wrong-place }{ anskey }{ keyanspic }
+ }
+ }
+%% Internal function for msg when |\anskey| is inner, math-mode or arg is empty.
+\cs_new_protected:Nn \__enumext_anskey_safe_inner:
+ {
+ \int_incr:N \l__enumext_anskey_level_int
+ \int_compare:nNnT { \l__enumext_anskey_level_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { anskey-nested }
+ }
+ \bool_if:NF \l__enumext_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 }
+ }
+ }
+\cs_new_protected:Nn \__enumext_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: }
+ }
+%% Hooks for |anskey*| environment out off |enumext| and |enumext*| environments.
+\__enumext_before_env:nn { enumext }
+ {
+ \bool_lazy_and:nnT
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 0 } }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 0 } }
+ {
+ \cs_if_free:cF { __scontents_anskey*_env_begin: }
+ {
+ \msg_error:nnn { enumext } { anskey-env-error } { anskey* }
+ }
+ }
+ }
+\__enumext_before_env:nn { enumext* }
+ {
+ \bool_lazy_and:nnT
+ { \int_compare_p:nNn { \l__enumext_level_int } = { 0 } }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 0 } }
+ {
+ \cs_if_free:cF { __scontents_anskey*_env_begin: }
+ {
+ \msg_error:nnn { enumext } { anskey-env-error } { anskey* }
+ }
+ }
+ }
+%% Hooks for |anskey*| inside the |keyans|, |keyans*| and |keyanspic| environments, math-mode ans not number |\item|.
+\__enumext_before_env:nn { anskey* }
+ {
+ \int_compare:nNnT { \l__enumext_keyans_level_int } = { 1 }
+ {
+ \msg_error:nnn { enumext } { anskey-env-wrong }{ keyans }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_h_int } = { 1 }
+ {
+ \msg_error:nnn { enumext } { anskey-env-wrong } { keyans* }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_pic_level_int } = { 1 }
+ {
+ \msg_error:nnn { enumext } { anskey-env-wrong } { keyanspic }
+ }
+ \bool_if:NF \l__enumext_item_number_bool
+ {
+ \msg_error:nn { enumext } { anskey-unnumber-item }
+ }
+ \mode_if_math:T
+ {
+ \msg_error:nnn { enumext } { anskey-math-mode } { anskey* }
+ }
+ }
+%% Function for define |anskey*| environment using scontents.
+\cs_new_protected:Npn \__enumext_anskey_env_make:n #1
+ {
+ \bool_if:NT \l__enumext_anskey_env_bool
+ {
+ \newenvsc{anskey*}[store-env=#1,print-env=false]
+ \__enumext_anskey_env_exec:
+ }
+ }
+\cs_generate_variant:Nn \__enumext_anskey_env_make:n { V }
+%% Define keys for |anskey*| environment using scontents PATH.
+\cs_new_protected:Nn \__enumext_anskey_env_define_keys:
+ {
+ \keys_define:nn { scontents / scontents }
+ {
+ break-col .bool_gset:N = \g__enumext_store_columns_break_bool,
+ break-col .default:n = true,
+ break-col .value_forbidden:n = true,
+ item-join .int_gset:N = \g__enumext_store_item_join_int,
+ item-join .value_required:n = true,
+ item-star .bool_gset:N = \g__enumext_store_item_star_bool,
+ item-star .default:n = true,
+ item-star .value_forbidden:n = true,
+ item-sym* .tl_gset:N = \g__enumext_store_item_symbol_tl,
+ item-sym* .value_required:n = true,
+ item-pos* .dim_gset:N = \g__enumext_store_item_symbol_sep_dim,
+ item-pos* .value_required:n = true,
+ print-env .undefine:,
+ store-env .undefine:,
+ write-out .undefine:,
+ unknown .code:n = { \__enumext_anskey_env_unknown:n {##1} },
+ }
+ }
+\cs_new_protected:Npn \__enumext_anskey_env_unknown:n #1
+ {
+ \exp_args:NV \__enumext_anskey_env_unknown:nn \l_keys_key_str {#1}
+ }
+\cs_new_protected:Npn \__enumext_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}
+ }
+ }
+%% Restore keys for |scontents| environment.
+\cs_new_protected:Nn \__enumext_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} },
+ }
+ }
+\cs_new_protected:Npn \__enumext_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
+ }
+ }
+%% Function for exec all code for |anskey*| environment.
+\cs_new_protected:Nn \__enumext_anskey_env_exec:
+ {
+ \__enumext_before_env:nn { anskey* }
+ {
+ \__enumext_anskey_env_define_keys:
+ }
+ \hook_if_empty:nF {env/anskey*/after}
+ {
+ \hook_gremove_code:nn {env/anskey*/after} { * }
+ }
+ \__enumext_after_env:nn { anskey* }
+ {
+ \__enumext_anskey_env_save_keys:
+ \tl_clear:N \l__enumext_store_anskey_env_tl
+ \tl_clear:N \l__enumext_store_anskey_opt_tl
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \tl_gset:Ne \l__enumext_store_anskey_env_tl
+ {
+ \seq_item:ce { g__scontents_name_ \l__enumext_store_name_tl _seq } { -1 }
+ }
+ \regex_match:nVTF
+ { ^\s* \z | ^\s* \u{c__scontents_hidden_space_str} \z }
+ \l__enumext_store_anskey_env_tl
+ {
+ \msg_error:nn { enumext } { anskey-empty-arg }
+ }
+ {
+ \__enumext_anskey_env_store:
+ }
+ }
+ \__enumext_anskey_env_clean_vars:
+ \__enumext_anskey_env_reset_keys:
+ }
+ }
+\cs_new_protected:Nn \__enumext_anskey_env_save_keys:
+ {
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \g__enumext_store_columns_break_bool }
+ { \bool_not_p:n { \l__enumext_starred_bool } }
+ {
+ \tl_put_left:Ne \l__enumext_store_anskey_opt_tl { ,break-col, }
+ }
+ \bool_lazy_and:nnT
+ { \bool_not_p:n { \l__enumext_starred_bool } }
+ { \int_compare_p:nNn { \g__enumext_store_item_join_int } > { 1 } }
+ {
+ \tl_put_left::Ne \l__enumext_store_anskey_opt_tl
+ {
+ ,item-join = \exp_not:V \g__enumext_store_item_join_int,
+ }
+ }
+ \bool_if:NT \g__enumext_store_item_star_bool
+ {
+ \tl_put_left:Ne \l__enumext_store_anskey_opt_tl
+ {
+ ,item-star,
+ }
+ \tl_if_empty:NF \g__enumext_store_item_symbol_tl
+ {
+ \tl_put_left:Ne \l__enumext_store_anskey_opt_tl
+ {
+ ,item-sym* = \exp_not:V \g__enumext_store_item_symbol_tl,
+ }
+ }
+ \dim_compare:nT
+ {
+ \g__enumext_store_item_symbol_sep_dim != \c_zero_dim
+ }
+ {
+ \tl_put_left:Ne \l__enumext_store_anskey_opt_tl
+ {
+ ,item-pos* = \exp_not:V \g__enumext_store_item_symbol_sep_dim,
+ }
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_anskey_env_store:
+ {
+ \group_begin:
+ \tl_if_empty:NTF \l__enumext_store_anskey_opt_tl
+ {
+ \exp_args:Ne
+ \__enumext_store_anskey_code:n
+ {
+ \__enumext_rescan_anskey_env:n { \l__enumext_store_anskey_env_tl }
+ }
+ }
+ {
+ \keys_set_known:nV { enumext / anskey } \l__enumext_store_anskey_opt_tl
+ \exp_args:Ne
+ \__enumext_store_anskey_code:n
+ {
+ \__enumext_rescan_anskey_env:n { \l__enumext_store_anskey_env_tl }
+ }
+ }
+ \group_end:
+ }
+\cs_new_protected:Nn \__enumext_anskey_env_clean_vars:
+ {
+ \bool_gset_false:N \g__enumext_store_columns_break_bool
+ \int_gzero:N \g__enumext_store_item_join_int
+ \bool_gset_false:N \g__enumext_store_item_star_bool
+ \tl_gclear:N \g__enumext_store_item_symbol_tl
+ \dim_gzero:N \g__enumext_store_item_symbol_sep_dim
+ }
+%% Function internal checking answer mechanism, clean vars and undefine |anskey*| environment.
+\cs_new_protected:Nn \__enumext_execute_after_env:
+ {
+ \int_compare:nNnT { \l__enumext_level_int } = { 0 }
+ {
+ \tl_if_empty:NF \g__enumext_store_name_tl
+ {
+ \__enumext_stop_save_ans_msg:
+ \__enumext_item_answer_diff:
+ \__enumext_log_global_vars:
+ \__enumext_log_answer_vars:
+ \bool_if:NTF \g__enumext_check_ans_key_bool
+ {
+ \__enumext_check_ans_show:
+ }
+ { \__enumext_check_ans_log: }
+ \__enumext_undefine_anskey_env:
+ }
+ \__enumext_reset_global_vars:
+ }
+ }
+%% Function for storing in prop list for |keyans| and |keyanspic| environments.
+\cs_new_protected:Npn \__enumext_keyans_addto_prop:n #1
+ {
+ \tl_clear:N \l__enumext_store_current_label_tl
+ \int_compare:nNnTF { \l__enumext_keyans_pic_level_int } = { 1 }
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl { \l__enumext_label_vi_tl }
+ }
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl { \l__enumext_label_v_tl }
+ }
+ \tl_if_novalue:nF { #1 }
+ {
+ \tl_if_empty:NF \l__enumext_store_keyans_item_opt_sep_tl
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl
+ {
+ \l__enumext_store_keyans_item_opt_sep_tl
+ }
+ }
+ \tl_put_right:Ne \l__enumext_store_current_label_tl { #1 }
+ }
+ \__enumext_store_addto_prop:V \l__enumext_store_current_label_tl
+ }
+%% Internal label and ref function for |keyans|, |keyans*| and |keyanspic| environments.
+\cs_new_protected:Nn \__enumext_keyans_store_ref:
+ {
+ \bool_if:NT \l__enumext_store_ref_key_bool
+ {
+ \cs_set_protected:Npn \__enumext_tmp:n ##1
+ {
+ \tl_set_eq:cc { l__enumext_label_copy_##1_tl } { l__enumext_label_##1_tl }
+ \tl_reverse:c { l__enumext_label_copy_##1_tl }
+ \tl_remove_once:cn { l__enumext_label_copy_##1_tl } { . }
+ \tl_reverse:c { l__enumext_label_copy_##1_tl }
+ }
+ \clist_map_inline:nn { i, v, vi, vii, viii } { \__enumext_tmp:n {##1} }
+ \__enumext_keyans_store_ref_aux_i:
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_store_ref_aux_i:
+ {
+ \bool_if:NT \g__enumext_starred_bool
+ {
+ \tl_set_eq:NN \l__enumext_label_copy_i_tl \l__enumext_label_copy_vii_tl
+ }
+ \int_compare:nNnT { \l__enumext_keyans_pic_level_int } = { 1 }
+ {
+ \tl_put_right:Ne \l__enumext_newlabel_arg_two_tl
+ { \l__enumext_label_copy_i_tl . \l__enumext_label_copy_vi_tl }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_int } = { 1 }
+ {
+ \tl_put_right:Ne \l__enumext_newlabel_arg_two_tl
+ { \l__enumext_label_copy_i_tl . \l__enumext_label_copy_v_tl }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_h_int } = { 1 }
+ {
+ \tl_put_right:Ne \l__enumext_newlabel_arg_two_tl
+ { \l__enumext_label_copy_i_tl . \l__enumext_label_copy_viii_tl }
+ }
+ \tl_put_right:Ne \l__enumext_newlabel_arg_one_tl
+ {
+ \l__enumext_store_name_tl \c_colon_str
+ \int_eval:n { \prop_count:c { g__enumext_ \l__enumext_store_name_tl _prop } }
+ }
+ \__enumext_keyans_store_ref_aux_ii:
+ }
+\cs_new_protected:Nn \__enumext_keyans_store_ref_aux_ii:
+ {
+ \tl_put_right:Ne \l__enumext_write_aux_file_tl
+ {
+ \__enumext_newlabel:nn
+ { \exp_not:V \l__enumext_newlabel_arg_one_tl }
+ { \l__enumext_newlabel_arg_two_tl }
+ }
+ \l__enumext_write_aux_file_tl
+ }
+%% Function for storing in sequence for |keyans| and |keyanspic| environments.
+\cs_new_protected:Npn \__enumext_keyans_addto_seq:n #1
+ {
+ \tl_clear:N \l__enumext_store_current_label_tl
+ \int_compare:nNnTF { \l__enumext_keyans_pic_level_int } = { 1 }
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl { \item \l__enumext_label_vi_tl }
+ }
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl { \item \l__enumext_label_v_tl }
+ }
+ \tl_if_novalue:nF { #1 }
+ {
+ \tl_if_empty:NF \l__enumext_store_keyans_item_opt_sep_tl
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl
+ {
+ \l__enumext_store_keyans_item_opt_sep_tl
+ }
+ }
+ \tl_put_right:Ne \l__enumext_store_current_label_tl { #1 }
+ }
+ \__enumext_keyans_addto_seq_link:
+ }
+\cs_new_protected:Nn \__enumext_keyans_addto_seq_link:
+ {
+ \bool_lazy_and:nnT
+ { \bool_if_p:N \l__enumext_store_ref_key_bool }
+ { \bool_if_p:N \l__enumext_hyperref_bool }
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl
+ {
+ \hfill \exp_not:N \hyperlink
+ {
+ \exp_not:V \l__enumext_newlabel_arg_one_tl
+ }
+ { \exp_not:V \l__enumext_mark_ref_sym_tl }
+ }
+ }
+ \__enumext_store_addto_seq:V \l__enumext_store_current_label_tl
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \int_gincr:N \g__enumext_item_anskey_int
+ }
+ }
+%% Function for |show-ans| and |show-pos| keys for |keyans| and |keyanspic| environments.
+\cs_new_protected:Npn \__enumext_keyans_show_left:n #1
+ {
+ \tl_if_novalue:nF { #1 }
+ {
+ \tl_set:Ne \l__enumext_store_current_opt_arg_tl { #1 }
+ }
+ \bool_if:NT \l__enumext_show_answer_bool
+ {
+ \__enumext_keyans_show_ans:
+ }
+ \bool_if:NT \l__enumext_show_position_bool
+ {
+ \__enumext_keyans_show_pos:
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_show_item_opt:
+ {
+ \tl_if_empty:NF \l__enumext_store_current_opt_arg_tl
+ {
+ \bool_lazy_or:nnT
+ { \bool_if_p:N \l__enumext_show_answer_bool }
+ { \bool_if_p:N \l__enumext_show_position_bool }
+ {
+ \__enumext_keyans_wrapper_opt:n { \l__enumext_store_current_opt_arg_tl } \c_space_tl
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_show_ans:
+ {
+ \bool_if:NT \l__enumext_starred_bool
+ {
+ \dim_set_eq:NN \l__enumext_labelwidth_i_dim \l__enumext_labelwidth_vii_dim
+ \dim_set_eq:NN \l__enumext_labelsep_i_dim \l__enumext_labelsep_vii_dim
+ }
+ \tl_put_left:Nn \l__enumext_label_v_tl
+ {
+ \__enumext_print_keyans_box:NN
+ \l__enumext_labelwidth_i_dim \l__enumext_labelsep_i_dim
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_show_pos:
+ {
+ \bool_if:NT \l__enumext_starred_bool
+ {
+ \dim_set_eq:NN \l__enumext_labelwidth_i_dim \l__enumext_labelwidth_vii_dim
+ \dim_set_eq:NN \l__enumext_labelsep_i_dim \l__enumext_labelsep_vii_dim
+ }
+ \int_compare:nNnTF { \l__enumext_keyans_pic_level_int } = { 1 }
+ {
+ \tl_set:Ne \l__enumext_mark_answer_sym_tl
+ {
+ \group_begin:
+ \exp_not:N \normalfont
+ \exp_not:N \footnotesize [ \int_eval:n
+ {
+ \prop_count:c { g__enumext_ \l__enumext_store_name_tl _prop }
+ }
+ ]
+ \group_end:
+ }
+ }
+ {
+ \tl_set:Ne \l__enumext_mark_answer_sym_tl
+ {
+ \group_begin:
+ \exp_not:N \normalfont
+ \exp_not:N \footnotesize [ \int_eval:n
+ {
+ \prop_count:c { g__enumext_ \l__enumext_store_name_tl _prop } + 1
+ }
+ ]
+ \group_end:
+ }
+ }
+ \tl_put_left:Nn \l__enumext_label_v_tl
+ {
+ \__enumext_print_keyans_box:NN
+ \l__enumext_labelwidth_i_dim \l__enumext_labelsep_i_dim
+ }
+ }
+%% Internal function for |\item| whit check-answer mechanism in |enumext| environment.
+\cs_new_protected:Npn \__enumext_default_item:n #1
+ {
+ \tl_if_novalue:nTF {#1}
+ {
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \int_gincr:N \g__enumext_item_number_int
+ \bool_set_true:N \l__enumext_item_number_bool
+ }
+ \bool_set_true:c { l__enumext_wrap_label_ \__enumext_level: _bool }
+ \__enumext_item_std:w \tl_use:c { l__enumext_fake_item_indent_ \__enumext_level: _tl }
+ }
+ {
+ \bool_set_eq:cc
+ { l__enumext_wrap_label_ \__enumext_level: _bool }
+ { l__enumext_wrap_label_opt_ \__enumext_level: _bool }
+ \__enumext_item_std:w [#1] \tl_use:c { l__enumext_fake_item_indent_ \__enumext_level: _tl }
+ }
+ }
+%% Internal function for |\item*[symb][sep]| whit check-answer mechanism in |enumext| environment.
+\cs_new_protected:Npn \__enumext_starred_item:nn #1 #2
+ {
+ \tl_if_novalue:nTF {#1}
+ {
+ \tl_gset_eq:Nc
+ \g__enumext_item_symbol_aux_tl { l__enumext_item_symbol_ \__enumext_level: _tl }
+ }
+ {
+ \tl_gset:Nn \g__enumext_item_symbol_aux_tl {#1}
+ }
+ \tl_if_novalue:nTF {#2}
+ {
+ \dim_set_eq:cc
+ { l__enumext_item_symbol_sep_ \__enumext_level: _dim }
+ { l__enumext_labelsep_ \__enumext_level: _dim }
+ }
+ {
+ \dim_set:cn { l__enumext_item_symbol_sep_ \__enumext_level: _dim } {#2}
+ }
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \int_gincr:N \g__enumext_item_number_int
+ \bool_set_true:N \l__enumext_item_number_bool
+ }
+ \bool_set_true:c { l__enumext_wrap_label_ \__enumext_level: _bool }
+ \__enumext_item_std:w \tl_use:c { l__enumext_fake_item_indent_ \__enumext_level: _tl }
+ }
+%% Function for |\item*[sym][sep]| in |\makelabel| for |enumext| environment.
+\cs_new_protected:Nn \__enumext_item_star_exec:
+ {
+ \tl_if_empty:cF { l__enumext_item_symbol_ \__enumext_level: _tl }
+ {
+ \mode_leave_vertical:
+ \skip_horizontal:n { -\dim_use:c { l__enumext_item_symbol_sep_ \__enumext_level: _dim } }
+ \hbox_overlap_left:n { \g__enumext_item_symbol_aux_tl }
+ \skip_horizontal:n { \dim_use:c { l__enumext_item_symbol_sep_ \__enumext_level: _dim } }
+ }
+ }
+%% Redefinition of |\item| for |\item*[sym][sep]| in |enumext| environment.
+\cs_new_protected:Nn \__enumext_redefine_item:
+ {
+ \RenewDocumentCommand \item { s o o }
+ {
+ \bool_if:nTF {##1}
+ {
+ \__enumext_starred_item:nn {##2} {##3}
+ }
+ { \__enumext_default_item:n {##2} }
+ }
+ }
+%% Redefinition of |\makelabel| for |\item| and |\item*[sym][sep]| in |enumext| environment.
+\cs_new_protected:Nn \__enumext_make_label:
+ {
+ \IfDocumentMetadataTF
+ {
+ \__enumext_make_label_box:
+ }
+ {
+ \bool_if:NTF \l__enumext_mode_box_bool
+ {
+ \__enumext_make_label_box:
+ }
+ {
+ \__enumext_make_label_std:
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_make_label_std:
+ {
+ \RenewDocumentCommand \makelabel { m }
+ {
+ \tl_use:c { l__enumext_label_fill_left_ \__enumext_level: _tl }
+ \tl_use:c { l__enumext_label_font_style_ \__enumext_level: _tl }
+ \bool_if:cTF { l__enumext_wrap_label_ \__enumext_level: _bool }
+ {
+ \__enumext_item_star_exec:
+ \use:c { __enumext_wrapper_label_ \__enumext_level: :n } { ##1 }
+ }
+ { ##1 }
+ \tl_use:c { l__enumext_label_fill_right_ \__enumext_level: _tl }
+ \tl_gclear:N \g__enumext_item_symbol_aux_tl
+ }
+ }
+\cs_new_protected:Nn \__enumext_make_label_box:
+ {
+ \RenewDocumentCommand \makelabel { m }
+ {
+ \strut\smash
+ {
+ \makebox
+ [ \dim_use:c { l__enumext_labelwidth_ \__enumext_level: _dim } ]
+ [ \str_use:c { l__enumext_align_label_pos_ \__enumext_level: _str } ]
+ {
+ \tl_use:c { l__enumext_label_font_style_ \__enumext_level: _tl }
+ \bool_if:cTF { l__enumext_wrap_label_ \__enumext_level: _bool }
+ {
+ \__enumext_item_star_exec:
+ \use:c { __enumext_wrapper_label_ \__enumext_level: :n } { ##1 }
+ }
+ { ##1 }
+ \tl_gclear:N \g__enumext_item_symbol_aux_tl
+ }
+ } % close smash
+ }
+ }
+%% Add |item-sym*| and |item-sep*| keys.
+\cs_set_protected:Npn \__enumext_tmp:nn #1 #2
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ item-sym* .tl_set:c = { l__enumext_item_symbol_#2_tl },
+ item-sym* .value_required:n = true,
+ item-sym* .initial:n = {\textasteriskcentered},
+ item-pos* .dim_set:c = { l__enumext_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}
+ }
+ { \__enumext_tmp:nn #1 }
+%% Add keys |unknown| for |keyans|, |keyans*| and |keyanspic| environments.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ unknown .code:n = { \__enumext_keyans_unknown_keys:n {##1} }
+ }
+ }
+\clist_map_inline:nn { keyans, keyans*, keyanspic } { \__enumext_tmp:n {#1} }
+\cs_new_protected:Npn \__enumext_keyans_unknown_keys:n #1
+ {
+ \exp_args:NV \__enumext_keyans_unknown_keys:nn \l_keys_key_str {#1}
+ }
+\cs_new_protected:Npn \__enumext_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}
+ }
+ }
+%% Add keys |unknown| for |enumext*| environment.
+\keys_define:nn { enumext / enumext* }
+ {
+ unknown .code:n = { \__enumext_starred_unknown_keys:n {#1} }
+ }
+\cs_new_protected:Npn \__enumext_starred_unknown_keys:n #1
+ {
+ \exp_args:NV \__enumext_starred_unknown_keys:nn \l_keys_key_str {#1}
+ }
+\cs_new_protected:Npn \__enumext_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}
+ }
+ }
+%% Add keys |unknown| for |enumext| environment.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \keys_define:nn { enumext / #1 }
+ {
+ unknown .code:n = { \__enumext_standar_unknown_keys:n {##1} }
+ }
+ }
+\clist_map_inline:nn { level-1,level-2,level-3,level-4 } { \__enumext_tmp:n {#1} }
+\cs_new_protected:Npn \__enumext_standar_unknown_keys:n #1
+ {
+ \exp_args:NV \__enumext_standar_unknown_keys:nn \l_keys_key_str {#1}
+ }
+\cs_new_protected:Npn \__enumext_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}
+ }
+ }
+\cs_new_protected:Npn \__enumext_keyans_default_item:n #1
+ {
+ \tl_if_novalue:nTF { #1 }
+ {
+ \bool_set_true:N \l__enumext_wrap_label_v_bool
+ \__enumext_item_std:w \tl_use:N \l__enumext_fake_item_indent_v_tl
+ }
+ {
+ \bool_set_eq:NN \l__enumext_wrap_label_v_bool \l__enumext_wrap_label_opt_v_bool
+ \__enumext_item_std:w [#1] \tl_use:N \l__enumext_fake_item_indent_v_tl
+ }
+ }
+\cs_new_protected:Npn \__enumext_keyans_starred_item:n #1
+ {
+ \tl_set_eq:NN \l__enumext_store_current_label_tmp_tl \l__enumext_label_v_tl
+ \__enumext_keyans_show_left:n { #1 }
+ \bool_set_true:N \l__enumext_wrap_label_v_bool
+ \__enumext_item_std:w \tl_use:N \l__enumext_fake_item_indent_v_tl
+ \__enumext_keyans_show_item_opt:
+ \tl_set_eq:NN \l__enumext_label_v_tl \l__enumext_store_current_label_tmp_tl
+ \__enumext_keyans_addto_prop:n { #1 }
+ \__enumext_keyans_store_ref:
+ \__enumext_keyans_addto_seq:n { #1 }
+ \int_gincr:N \g__enumext_check_starred_cmd_int
+ }
+%% Redefine |\item| for |keyans| environment.
+\cs_new_protected:Nn \__enumext_keyans_redefine_item:
+ {
+ \RenewDocumentCommand \item { s o }
+ {
+ \bool_if:nTF {##1}
+ {
+ \peek_remove_spaces:n
+ {
+ \__enumext_keyans_starred_item:n {##2}
+ }
+ }
+ {
+ \__enumext_keyans_default_item:n {##2}
+ }
+ }
+ }
+%% Redefine |\makelabel| for |keyans| environment.
+\cs_new_protected:Nn \__enumext_keyans_make_label:
+ {
+ \IfDocumentMetadataTF
+ {
+ \__enumext_keyans_make_label_box:
+ }
+ {
+ \bool_if:NTF \l__enumext_mode_box_bool
+ {
+ \__enumext_keyans_make_label_box:
+ }
+ {
+ \__enumext_keyans_make_label_std:
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_make_label_std:
+ {
+ \RenewDocumentCommand \makelabel { m }
+ {
+ \tl_use:N \l__enumext_label_fill_left_v_tl
+ \tl_use:N \l__enumext_label_font_style_v_tl
+ \bool_if:NTF \l__enumext_wrap_label_v_bool
+ {
+ \__enumext_wrapper_label_v:n { ##1 }
+ }
+ { ##1 }
+ \tl_use:N \l__enumext_label_fill_right_v_tl
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_make_label_box:
+ {
+ \RenewDocumentCommand \makelabel { m }
+ {
+ \strut\smash
+ {
+ \makebox[ \l__enumext_labelwidth_v_dim ][ \l__enumext_align_label_pos_v_str ]
+ {
+ \tl_use:N \l__enumext_label_font_style_v_tl
+ \bool_if:NTF \l__enumext_wrap_label_v_bool
+ {
+ \__enumext_wrapper_label_v:n { ##1 }
+ }
+ { ##1 }
+ }
+ }
+ }
+ }
+%% 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
+\cs_new_protected:Npn \__enumext_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 } }
+ }
+ \bool_if:nF #7 { \dim_set:Nn #4 { #1 + #2} }
+ \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 \__enumext_calc_hspace:NNNNNNN { ccccccc }
+%% Define "second arg" of list for |enumext| and |keyans|.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \cs_new_protected:cpn { __enumext_list_arg_two_#1: }
+ {
+ \__enumext_calc_hspace:ccccccc
+ { l__enumext_labelwidth_#1_dim } { l__enumext_labelsep_#1_dim }
+ { l__enumext_listoffset_#1_dim } { l__enumext_leftmargin_tmp_#1_dim }
+ { l__enumext_leftmargin_#1_dim } { l__enumext_itemindent_#1_dim }
+ { l__enumext_leftmargin_tmp_#1_bool }
+ \clist_map_inline:nn
+ { labelsep, labelwidth, itemindent, leftmargin, rightmargin, listparindent }
+ { \dim_set_eq:cc {####1} { l__enumext_####1_#1_dim } }
+ \clist_map_inline:nn { topsep, parsep, partopsep, itemsep }
+ { \skip_set_eq:cc {####1} { l__enumext_####1_#1_skip } }
+ \usecounter { enumX#1 }
+ \setcounter { enumX#1 } { \int_eval:n { \int_use:c { l__enumext_start_#1_int } - 1 } }
+ \str_if_eq:nnTF {#1} { v }
+ {
+ \__enumext_keyans_redefine_item:
+ \__enumext_keyans_make_label:
+ \__enumext_keyans_ref:
+ \__enumext_keyans_fake_item_indent:
+ \bool_if:cT { l__enumext_show_length_#1_bool }
+ {
+ \msg_term:nnnn { enumext } { list-lengths-not-nested } { v } { keyans }
+ }
+ }
+ {
+ \__enumext_redefine_item:
+ \__enumext_make_label:
+ \__enumext_standar_ref:
+ \__enumext_fake_item_indent:
+ \bool_if:cT { l__enumext_show_length_#1_bool }
+ {
+ \msg_term:nnne { enumext } { list-lengths } {#1}
+ { \int_use:N \l__enumext_level_int }
+ }
+ }
+ }
+ }
+\clist_map_inline:nn { i, ii, iii, iv, v } { \__enumext_tmp:n {#1} }
+%% Define "second arg" of list for |enumext*| and |keyans*|.
+\cs_set_protected:Npn \__enumext_tmp:n #1
+ {
+ \cs_new_protected:cpn { __enumext_list_arg_two_#1: }
+ {
+ \bool_set_true:c { l__enumext_leftmargin_tmp_#1_bool }
+ \dim_zero:c { l__enumext_leftmargin_tmp_#1_dim }
+ \__enumext_calc_hspace:ccccccc
+ { l__enumext_labelwidth_#1_dim } { l__enumext_labelsep_#1_dim }
+ { l__enumext_listoffset_#1_dim } { l__enumext_leftmargin_tmp_#1_dim }
+ { l__enumext_leftmargin_#1_dim } { l__enumext_itemindent_#1_dim }
+ { l__enumext_leftmargin_tmp_#1_bool }
+ \clist_map_inline:nn
+ { labelsep, labelwidth, itemindent, leftmargin, rightmargin, listparindent }
+ { \dim_set_eq:cc {####1} { l__enumext_####1_#1_dim } }
+ \clist_map_inline:nn { topsep, parsep, partopsep, itemsep }
+ { \skip_set_eq:cc {####1} { l__enumext_####1_#1_skip } }
+ \skip_set_eq:Nc \parsep { l__enumext_itemsep_#1_skip }
+ \skip_zero:N \partopsep
+ \usecounter { enumX#1 }
+ \setcounter { enumX#1 } { \int_eval:n { \int_use:c { l__enumext_start_#1_int } - 1 } }
+ \__enumext_starred_ref:
+ \str_if_eq:nnTF {#1} { vii }
+ {
+ \__enumext_fake_item_indent_vii:
+ \bool_if:cT { l__enumext_show_length_vii_bool }
+ { \msg_term:nnnn { enumext } { list-lengths-not-nested } { vii } { enumext* } }
+ }
+ {
+ \__enumext_fake_item_indent_viii:
+ \bool_if:cT { l__enumext_show_length_#1_bool }
+ { \msg_term:nnnn { enumext } { list-lengths-not-nested } { #1 } { keyans* } }
+ }
+ }
+ }
+\clist_map_inline:nn { vii, viii } { \__enumext_tmp:n {#1} }
+%% Safe exec for |enumext| environment.
+\cs_new_protected:Nn \__enumext_safe_exec:
+ {
+ \__enumext_is_not_nested:
+ \__enumext_internal_mini_page:
+ \int_incr:N \l__enumext_level_int
+ \int_compare:nNnT { \l__enumext_level_int } > { 4 }
+ { \msg_fatal:nn { enumext } { list-too-deep } }
+ \bool_set_true:N \l__enumext_standar_bool
+ \bool_set_false:N \l__enumext_starred_bool
+ \__enumext_is_on_first_level:
+ }
+%% Parse |key=val| and set default series and store keys in seq-name for \printkeyans for |enumext| environment.
+\cs_new_protected:Npn \__enumext_parse_keys:n #1
+ {
+ \tl_if_novalue:nF {#1}
+ {
+ \str_clear:N \l__enumext_series_str
+ \int_compare:nNnTF { \l__enumext_level_int } = { 1 }
+ {
+ \keys_set:nn { enumext / level-1 } {#1}
+ \__enumext_parse_series:n {#1}
+ \__enumext_nested_base_line_fix:
+ }
+ {
+ \exp_args:Ne \keys_set:nn
+ { enumext / level-\int_use:N \l__enumext_level_int } {#1}
+ }
+ \__enumext_store_active_keys:n {#1}
+ }
+ }
+%% Start storing structure in sequence for |save-ans| key in |enumext| environment.
+\cs_new_protected:Nn \__enumext_start_store_level:
+ {
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \l__enumext_store_active_bool }
+ { \bool_not_p:n { \l__enumext_keyans_env_bool } }
+ { \bool_if_p:N \g__enumext_standar_bool }
+ }
+ {
+ \int_compare:nNnT { \l__enumext_level_int } > { 1 }
+ {
+ \bool_set_true:c { l__enumext_store_upper_level_ \__enumext_level: _bool }
+ \__enumext_store_level_open:
+ }
+ }
+ \bool_lazy_all:nT
+ {
+ { \bool_if_p:N \l__enumext_store_active_bool }
+ { \bool_not_p:n { \l__enumext_keyans_env_bool } }
+ { \int_compare_p:nNn { \l__enumext_level_h_int } = { 1 } }
+ }
+ {
+ \int_compare:nNnT { \l__enumext_level_int } > { 0 }
+ {
+ \bool_set_true:c { l__enumext_store_upper_level_ \__enumext_level: _bool }
+ \__enumext_store_level_open:
+ }
+ }
+ }
+%% Stop storing structure in sequence for |save-ans| key in |enumext| environment.
+\cs_new_protected:Nn \__enumext_stop_store_level:
+ {
+ \bool_if:cT { l__enumext_store_upper_level_ \__enumext_level: _bool }
+ {
+ \__enumext_store_level_close:
+ }
+ }
+\cs_new_protected:Nn \__enumext_multicols_start:
+ {
+ \int_compare:nNnT
+ { \int_use:c { l__enumext_columns_ \__enumext_level: _int } } > { 1 }
+ {
+ \dim_compare:nNnT
+ { \dim_use:c { l__enumext_columns_sep_ \__enumext_level: _dim } } = { \c_zero_dim }
+ {
+ \dim_set:cn { l__enumext_columns_sep_ \__enumext_level: _dim }
+ {
+ ( \dim_use:c { l__enumext_labelwidth_ \__enumext_level: _dim }
+ + \dim_use:c { l__enumext_labelsep_ \__enumext_level: _dim }
+ ) / \int_use:c { l__enumext_columns_ \__enumext_level: _int }
+ - \dim_use:c { l__enumext_listoffset_ \__enumext_level: _dim }
+ }
+ }
+ \dim_set_eq:Nc \columnsep { l__enumext_columns_sep_ \__enumext_level: _dim }
+ \int_compare:nNnT { \l__enumext_level_int } > { 1 }
+ {
+ \dim_zero:N \columnseprule
+ }
+ \bool_if:cF { l__enumext_minipage_active_ \__enumext_level: _bool }
+ {
+ \skip_zero:N \multicolsep
+ \__enumext_multi_addvspace:
+ }
+ \raggedcolumns
+ \begin{multicols}{ \int_use:c { l__enumext_columns_ \__enumext_level: _int } }
+ }
+ }
+\cs_new_protected:Nn \__enumext_multicols_stop:
+ {
+ \int_compare:nNnTF
+ { \int_use:c { l__enumext_columns_ \__enumext_level: _int } } > { 1 }
+ {
+ \__enumext_stop_list:
+ \__enumext_stop_store_level:
+ \end{multicols}
+ \__enumext_unskip_unkern:
+ \__enumext_unskip_unkern:
+ \par\addvspace{ \skip_use:c { l__enumext_multicols_below_ \__enumext_level: _skip } }
+ }
+ {
+ \__enumext_stop_list:
+ \__enumext_stop_store_level:
+ }
+ }
+\cs_new_protected:Nn \__enumext_before_list:
+ {
+ \__enumext_vspace_above:
+ \__enumext_before_args_exec:
+ \__enumext_check_ans_active:
+%% Set |mini-env| width value.
+ \dim_compare:nNnT
+ { \dim_use:c { l__enumext_minipage_right_ \__enumext_level: _dim } } > { \c_zero_dim }
+ {
+ \dim_set:cn { l__enumext_minipage_left_ \__enumext_level: _dim }
+ {
+ \linewidth
+ - \dim_use:c { l__enumext_minipage_right_ \__enumext_level: _dim }
+ - \dim_use:c { l__enumext_minipage_hsep_ \__enumext_level: _dim }
+ }
+%% Use internal minipage with |\nointerlineskip| and |\addvspace| here
+ \bool_set_true:c { l__enumext_minipage_active_ \__enumext_level: _bool }
+ \int_gincr:N \g__enumext_minipage_stat_int
+ \__enumext_minipage_add_space:
+ \noindent
+ \__enumext_mini_page{ \dim_use:c { l__enumext_minipage_left_ \__enumext_level: _dim } }
+ }
+ \__enumext_multicols_start:
+ }
+\cs_new_protected:Nn \__enumext_second_part:
+ {
+ \bool_if:cTF { l__enumext_minipage_active_ \__enumext_level: _bool }
+ {
+ \int_compare:nNnT { \g__enumext_minipage_stat_int } = { 1 }
+ {
+ \msg_warning:nn { enumext } { missing-miniright }
+ \miniright
+ }
+ \int_gzero:N \g__enumext_minipage_stat_int
+ \__enumext_unskip_unkern: % remove topsep + [partopsep]
+ \end__enumext_mini_page
+ }
+ {
+ \__enumext_multicols_stop:
+ }
+ \__enumext_after_stop_list:
+ \__enumext_check_ans_key_hook:
+ \__enumext_vspace_below:
+ \bool_set_false:N \l__enumext_standar_bool
+ \__enumext_resume_save_counter:
+ }
+%% Set |\itemwidth| for |enumext| environment.
+\cs_new_protected:Nn \__enumext_set_item_width:
+ {
+ \dim_set:Nn \itemwidth { \linewidth }
+ \dim_compare:nT
+ {
+ \dim_use:c { l__enumext_listoffset_ \__enumext_level: _dim } != \c_zero_dim
+ }
+ {
+ \dim_sub:Nn \itemwidth
+ {
+ \dim_use:c { l__enumext_listoffset_ \__enumext_level: _dim }
+ }
+ }
+ }
+%% Definition of |enumext| environment.
+\NewDocumentEnvironment{enumext}{ O{} }
+ {
+ \__enumext_safe_exec:
+ \__enumext_parse_keys:n {#1}
+ \__enumext_before_list:
+ \__enumext_start_store_level:
+ \__enumext_start_list:nn
+ { \tl_use:c { l__enumext_label_ \__enumext_level: _tl } }
+ {
+ \use:c { __enumext_list_arg_two_ \__enumext_level: : }
+ \__enumext_before_keys_exec:
+ }
+ \__enumext_set_item_width:
+ \__enumext_after_args_exec:
+ }
+ {
+ \__enumext_second_part:
+ }
+%% Execute |check-ans| key out of |enumext| environment.
+\__enumext_after_env:nn {enumext}
+ {
+ \__enumext_execute_after_env:
+ }
+%% Function for check nested level in |keyans| environment.
+\cs_new_protected:Nn \__enumext_keyans_safe_exec:
+ {
+ \bool_if:NF \l__enumext_store_active_bool
+ {
+ \msg_error:nnnn { enumext } { wrong-place }{ keyans }{ save-ans }
+ }
+ \int_incr:N \l__enumext_keyans_level_int
+ \bool_set_true:N \l__enumext_keyans_env_bool
+ \__enumext_keyans_name_and_start:
+ % Set false for interfering with enumext nested in keyans (yes, its possible and crayze)
+ \bool_set_false:N \l__enumext_store_active_bool
+ \int_compare:nNnT { \l__enumext_keyans_level_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { keyans-nested }
+ }
+ \int_compare:nNnT { \l__enumext_level_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { keyans-wrong-level }
+ }
+ }
+%% Function for parse |key=val| in |keyans|.
+\cs_new_protected:Npn \__enumext_keyans_parse_keys:n #1
+ {
+ \keys_set:nn { enumext / keyans } {#1}
+ }
+%% Internal functions for |keyans| environment.
+\cs_new_protected:Nn \__enumext_before_list_v:
+ {
+ \__enumext_vspace_above_v:
+ \__enumext_before_args_exec_v:
+ \dim_compare:nNnT { \l__enumext_minipage_right_v_dim } > { \c_zero_dim }
+ {
+ \dim_set:Nn \l__enumext_minipage_left_v_dim
+ {
+ \linewidth - \l__enumext_minipage_right_v_dim - \l__enumext_minipage_hsep_v_dim
+ }
+ \bool_set_true:N \l__enumext_minipage_active_v_bool
+ \int_gincr:N \g__enumext_minipage_stat_int
+ \__enumext_keyans_minipage_add_space:
+ \__enumext_mini_page{ \l__enumext_minipage_left_v_dim }
+ }
+ \__enumext_keyans_multicols_start:
+ }
+\cs_new_protected:Nn \__enumext_keyans_multicols_start:
+ {
+ \int_compare:nNnT { \l__enumext_columns_v_int } > { 1 }
+ {
+ \dim_compare:nNnT { \l__enumext_columns_sep_v_dim } = { \c_zero_dim }
+ {
+ \dim_set:Nn \l__enumext_columns_sep_v_dim
+ {
+ (
+ \l__enumext_labelwidth_v_dim + \l__enumext_labelsep_v_dim
+ ) / \l__enumext_columns_v_int
+ - \l__enumext_listoffset_v_dim
+ }
+ }
+ \dim_set_eq:NN \columnsep \l__enumext_columns_sep_v_dim
+ \dim_zero:N \columnseprule % no rule here
+ \bool_if:NF \l__enumext_minipage_active_v_bool
+ {
+ \skip_zero:N \multicolsep
+ \__enumext_keyans_multi_addvspace:
+ }
+ \raggedcolumns
+ \begin{multicols}{ \l__enumext_columns_v_int }
+ }
+ }
+\cs_new_protected:Nn \__enumext_keyans_multicols_stop:
+ {
+ \int_compare:nNnTF { \l__enumext_columns_v_int } > { 1 }
+ {
+ \__enumext_stop_list:
+ \end{multicols}
+ \__enumext_unskip_unkern:
+ \__enumext_unskip_unkern:
+ \par\addvspace{ \l__enumext_multicols_below_v_skip }
+ }
+ {
+ \__enumext_stop_list:
+ }
+ }
+\cs_new_protected:Nn \__enumext_second_part_v:
+ {
+ \bool_if:NTF \l__enumext_minipage_active_v_bool
+ {
+ \int_compare:nNnT { \g__enumext_minipage_stat_int } = { 1 }
+ {
+ \msg_warning:nn { enumext } { missing-miniright }
+ \miniright
+ }
+ \int_gzero:N \g__enumext_minipage_stat_int
+ \__enumext_unskip_unkern: % remove \topsep + [\partopsep]
+ \end__enumext_mini_page
+ \par\addvspace{ \l__enumext_minipage_after_skip }
+ }
+ {
+ \__enumext_keyans_multicols_stop:
+ }
+ \bool_set_false:N \l__enumext_keyans_env_bool
+ \__enumext_after_stop_list_v:
+ \__enumext_vspace_below_v:
+ }
+%% Set |\itemwidth| for |keyans| environment.
+\cs_new_protected:Nn \__enumext_keyans_set_item_width:
+ {
+ \dim_set:Nn \itemwidth { \linewidth }
+ \dim_compare:nT
+ {
+ \l__enumext_listoffset_v_dim != \c_zero_dim
+ }
+ {
+ \dim_sub:Nn \itemwidth { \l__enumext_listoffset_v_dim }
+ }
+ }
+%% Definition of |keyans| environment.
+\NewDocumentEnvironment{keyans}{ O{} }
+ {
+ \__enumext_keyans_safe_exec:
+ \__enumext_keyans_parse_keys:n {#1}
+ \__enumext_before_list_v:
+ \__enumext_start_list:nn
+ { \tl_use:N \l__enumext_label_v_tl }
+ {
+ \__enumext_list_arg_two_v:
+ \__enumext_before_keys_exec_v:
+ }
+ \__enumext_keyans_set_item_width:
+ \__enumext_after_args_exec_v:
+ }
+ {
+ \__enumext_check_starred_cmd:n { item }
+ \__enumext_second_part_v:
+ }
+%% Implement socket for tagging support in |enumext*| and |keyans*| environments.
+\socket_new:nn {tagsupport/__enumext/starred}{ 1 }
+\socket_new_plug:nnn {tagsupport/__enumext/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/__enumext/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/__enumext/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}
+ }
+%% Wrap socket in conditional functions for tagging |enumext*| and |keyans*| environments.
+\cs_new_protected_nopar:Npn \__enumext_start_list_tag:n #1
+ {
+ \IfDocumentMetadataTF
+ {
+ \socket_assign_plug:nn {tagsupport/__enumext/starred} {start-list-tags}
+ \socket_use:nn {tagsupport/__enumext/starred} {#1}
+ } {}
+ }
+\cs_new_protected_nopar:Nn \__enumext_stop_start_list_tag:
+ {
+ \IfDocumentMetadataTF
+ {
+ \socket_assign_plug:nn {tagsupport/__enumext/starred} {stop-start-tags}
+ \socket_use:nn {tagsupport/__enumext/starred} { }
+ } {}
+ }
+\cs_new_protected_nopar:Npn \__enumext_stop_list_tag:n #1
+ {
+ \IfDocumentMetadataTF
+ {
+ \socket_assign_plug:nn {tagsupport/__enumext/starred} {stop-list-tags}
+ \socket_use:nn {tagsupport/__enumext/starred} {#1}
+ } {}
+ }
+%% Implement socket for tagging support in |keyanspic| environment.
+\socket_new:nn {tagsupport/__enumext/keyanspic}{ 0 }
+\socket_new_plug:nnn {tagsupport/__enumext/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/__enumext/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/__enumext/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}
+ }
+%% Wrap socket in conditional functions for tagging |keyanspic| environment.
+\cs_new_protected_nopar:Nn \__enumext_anspic_start_list_tag:
+ {
+ \IfDocumentMetadataTF
+ {
+ \socket_assign_plug:nn {tagsupport/__enumext/keyanspic} {start-list-tags}
+ \socket_use:n {tagsupport/__enumext/keyanspic}
+ } {}
+ }
+\cs_new_protected_nopar:Nn \__enumext_anspic_stop_start_list_tag:
+ {
+ \IfDocumentMetadataTF
+ {
+ \socket_assign_plug:nn {tagsupport/__enumext/keyanspic} {stop-start-tags}
+ \socket_use:n {tagsupport/__enumext/keyanspic}
+ } {}
+ }
+\cs_new_protected_nopar:Nn \__enumext_anspic_stop_list_tag:
+ {
+ \IfDocumentMetadataTF
+ {
+ \socket_assign_plug:nn {tagsupport/__enumext/keyanspic} {stop-list-tags}
+ \socket_use:n {tagsupport/__enumext/keyanspic}
+ } {}
+ }
+%% Add keys for |keyanspic| environment.
+\keys_define:nn { enumext / keyanspic }
+ {
+ label-pos .choice:,
+ label-pos / above .code:n =
+ \bool_set_true:N \l__enumext_anspic_label_above_bool
+ \str_set:Nn \l__enumext_anspic_mini_pos_str { t },
+ label-pos / below .code:n =
+ \bool_set_false:N \l__enumext_anspic_label_above_bool
+ \str_set:Nn \l__enumext_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__enumext_anspic_label_sep_skip,
+ label-sep .value_required:n = true,
+ layout-sty .tl_set:N = \l__enumext_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 = { \__enumext_keyans_unknown_keys:n {#1} }
+ }
+%% Internal check code for |keyanspic| environment.
+\cs_new_protected:Nn \__enumext_keyans_pic_safe_exec:
+ {
+ \int_incr:N \l__enumext_keyans_pic_level_int
+ \int_compare:nNnT { \l__enumext_keyans_pic_level_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { keyanspic-nested }
+ }
+ \__enumext_keyans_name_and_start:
+ }
+\cs_new_protected:Npn \__enumext_keyans_pic_parse_keys:n #1
+ {
+ \tl_if_novalue:nF {#1}
+ {
+ \keys_set:nn { enumext / keyanspic } {#1}
+ }
+ }
+\cs_new_protected:Npn \__enumext_keyans_pic_skip_abs:N #1
+ {
+ \dim_compare:nNnT { #1 } < { \c_zero_dim }
+ {
+ \skip_set:Nn #1 { -#1 }
+ }
+ }
+\cs_new_protected:Npn \__enumext_keyans_pic_arg_two:
+ {
+ \bool_set_false:N \l__enumext_leftmargin_tmp_v_bool
+ \__enumext_list_arg_two_v:
+ \__enumext_keyans_pic_skip_abs:N \parsep
+ \bool_if:NF \l__enumext_anspic_label_above_bool
+ {
+ \stepcounter { enumXv }
+ \hbox_set:Nn \l__enumext_anspic_label_box { \l__enumext_label_v_tl }
+ \dim_set:Nn \l__enumext_anspic_label_htdp_dim
+ {
+ \box_ht_plus_dp:N \l__enumext_anspic_label_box
+ }
+ \skip_add:Nn \parsep
+ {
+ \l__enumext_anspic_label_htdp_dim
+ + \box_dp:N \strutbox
+ + \l__enumext_anspic_label_sep_skip
+ }
+ }
+ \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
+ }
+%% Define |keyanspic| environment.
+\NewDocumentEnvironment{keyanspic}{ o }
+ {
+ \__enumext_keyans_pic_safe_exec:
+ \__enumext_keyans_pic_parse_keys:n {#1}
+ \begin{list} { } { \__enumext_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}
+ } { }
+ }
+ {
+ \IfDocumentMetadataTF
+ {
+ \tag_resume:n {keyanspic}
+ \tag_mc_end_push:
+ \tag_struct_begin:n {tag=L,attribute=enumerate}
+ } { }
+ \__enumext_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 {}
+ } { }
+ \__enumext_check_starred_cmd:n { anspic }
+ \setcounter { enumXvi } { 0 }
+ \bool_if:NTF \l__enumext_anspic_label_above_bool
+ {
+ \par\addvspace{ 0.5\box_dp:N \strutbox }
+ }
+ {
+ \par
+ \addvspace
+ {
+ \dim_eval:n
+ {
+ \l__enumext_anspic_label_htdp_dim + \box_ht_plus_dp:N \strutbox
+ + \l__enumext_anspic_label_sep_skip + \l__enumext_topsep_v_skip
+ }
+ }
+ }
+ }
+%% Define |\anspic| for |keyanspic| environment.
+\NewDocumentCommand \anspic { s o +m }
+ {
+ \bool_if:NF \l__enumext_store_active_bool
+ {
+ \msg_error:nnnn { enumext } { wrong-place }{ keyanspic }{ save-ans }
+ }
+ \int_compare:nNnT { \l__enumext_level_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { keyanspic-wrong-level }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_int } = { 1 }
+ {
+ \msg_error:nnnn { enumext } { command-wrong-place }{ anspic }{ keyans }
+ }
+ \seq_put_right:Nn \l__enumext_anspic_args_seq
+ {
+ \__enumext_anspic_args:nnn { #1 } { #2 } { #3 }
+ }
+ }
+%% Set the height plus depth off body arg in dim var for |\anspic|.
+\cs_new_protected:Npn \__enumext_anspic_body_dim:n #1
+ {
+ \bool_if:NF \l__enumext_anspic_label_above_bool
+ {
+ \IfDocumentMetadataTF
+ {
+ \tag_suspend:n {keyanspic}
+ } { }
+ \vbox_set:Nn \l__enumext_anspic_body_box { #1 }
+ \dim_set:Nn \l__enumext_anspic_body_htdp_dim
+ {
+ \box_ht_plus_dp:N \l__enumext_anspic_body_box
+ }
+ \IfDocumentMetadataTF
+ {
+ \tag_resume:n {keyanspic}
+ } { }
+ }
+ }
+%% Process and store label and [opt] for |\anspic|.
+\cs_new_protected:Npn \__enumext_anspic_label:nn #1 #2
+ {
+ \makebox[ \l__enumext_anspic_mini_width_dim ][ c ]
+ {
+ \bool_if:nT { #1 }
+ {
+ \__enumext_keyans_addto_prop:n { #2 }
+ \__enumext_keyans_store_ref:
+ \__enumext_keyans_addto_seq:n { #2 }
+ \int_gincr:N \g__enumext_check_starred_cmd_int
+ \bool_lazy_or:nnT
+ { \bool_if_p:N \l__enumext_show_answer_bool }
+ { \bool_if_p:N \l__enumext_show_position_bool }
+ {
+ \tl_set_eq:NN \l__enumext_label_v_tl \l__enumext_label_vi_tl
+ \__enumext_keyans_show_left:n { #2 }
+ \tl_set_eq:NN \l__enumext_label_vi_tl \l__enumext_label_v_tl
+ }
+ }
+ \tl_use:N \l__enumext_label_font_style_v_tl
+ \__enumext_wrapper_label_v:n { \l__enumext_label_vi_tl }
+ \__enumext_keyans_show_item_opt:
+ }
+ }
+%% Set position of labels for |\anspic|.
+\cs_new_protected:Npn \__enumext_anspic_label_pos:nnn #1 #2 #3
+ {
+ \stepcounter { enumXvi }
+ \__enumext_anspic_body_dim:n { #3 }
+ \bool_if:NTF \l__enumext_anspic_label_above_bool
+ {
+ \__enumext_anspic_label:nn { #1 } { #2 }
+ }
+ {
+ \raisebox
+ {
+ -\dim_eval:n
+ {
+ \l__enumext_anspic_label_htdp_dim
+ + \l__enumext_anspic_body_htdp_dim
+ + \box_dp:N \strutbox
+ + \l__enumext_anspic_label_sep_skip
+ }
+ }
+ [ 0pt ] [ 0pt ]
+ {
+ \__enumext_anspic_label:nn { #1 } { #2 }
+ }
+ }
+ }
+%% Process all code for |\anspic| with tagging PDF support.
+\cs_new_protected:Nn \__enumext_anspic_args:nnn
+ {
+ \__enumext_anspic_start_list_tag:
+ \__enumext_anspic_label_pos:nnn { #1 } { #2 } { #3 }
+ \__enumext_anspic_stop_start_list_tag:
+ \bool_if:NTF \l__enumext_anspic_label_above_bool
+ {
+ \\[\l__enumext_anspic_label_sep_skip] #3
+ }
+ {
+ \\ #3
+ }
+ \__enumext_anspic_stop_list_tag:
+ }
+\cs_new_protected:Nn \__enumext_anspic_print:n
+ {
+ \clist_map_function:nN { #1 } \__enumext_anspic_row:n
+ }
+\cs_generate_variant:Nn \__enumext_anspic_print:n { e, V }
+\cs_new_protected:Nn \__enumext_anspic_row:n
+ {
+ \dim_set:Nn \l__enumext_anspic_mini_width_dim { \linewidth / #1 }
+ \int_set:Nn \l__enumext_anspic_above_int { \l__enumext_anspic_below_int }
+ \int_set:Nn \l__enumext_anspic_below_int { \l__enumext_anspic_above_int + #1 }
+ \int_step_inline:nnn
+ { \l__enumext_anspic_above_int + 1 }
+ { \l__enumext_anspic_below_int }
+ {
+ \IfDocumentMetadataTF
+ {
+ \tag_suspend:n {minipage}
+ } { }
+ \begin{minipage}[ \l__enumext_anspic_mini_pos_str ]{ \l__enumext_anspic_mini_width_dim }
+ \centering
+ \seq_item:Nn \l__enumext_anspic_args_seq { ##1 }
+ \end{minipage}
+ \IfDocumentMetadataTF
+ {
+ \tag_resume:n {minipage}
+ } { }
+ }
+ \par
+ }
+\cs_new_protected:Nn \__enumext_anspic_exec:
+ {
+ \tl_if_empty:NTF \l__enumext_anspic_layout_style_tl
+ {
+ \__enumext_anspic_print:e { \seq_count:N \l__enumext_anspic_args_seq }
+ }
+ {
+ \__enumext_anspic_print:V \l__enumext_anspic_layout_style_tl
+ }
+ }
+%% Define default item width (columns width) for |enumext*| and |keyans*| environments.
+\cs_new_protected:Nn \__enumext_starred_columns_set_vii:
+ {
+ \dim_compare:nNnT { \l__enumext_columns_sep_vii_dim } = { \c_zero_dim }
+ {
+ \dim_set:Nn \l__enumext_columns_sep_vii_dim
+ {
+ ( \l__enumext_labelwidth_vii_dim + \l__enumext_labelsep_vii_dim )
+ / \l__enumext_columns_vii_int
+ }
+ }
+ \int_set:Nn \l__enumext_tmpa_vii_int { \l__enumext_columns_vii_int - 1 }
+ \dim_set:Nn \l__enumext_item_width_vii_dim
+ {
+ ( \linewidth - \l__enumext_columns_sep_vii_dim * \l__enumext_tmpa_vii_int )
+ / \l__enumext_columns_vii_int
+ - \l__enumext_labelwidth_vii_dim
+ - \l__enumext_labelsep_vii_dim
+ }
+ \dim_compare:nNnT { \l__enumext_rightmargin_vii_dim } > { \c_zero_dim }
+ {
+ \dim_sub:Nn \l__enumext_item_width_vii_dim
+ {
+ ( \l__enumext_rightmargin_vii_dim * \l__enumext_tmpa_vii_int )
+ / \l__enumext_columns_vii_int
+ }
+ \dim_add:Nn \l__enumext_columns_sep_vii_dim
+ {
+ \l__enumext_rightmargin_vii_dim
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_starred_columns_set_viii:
+ {
+ \dim_compare:nNnT { \l__enumext_columns_sep_viii_dim } = { \c_zero_dim }
+ {
+ \dim_set:Nn \l__enumext_columns_sep_viii_dim
+ {
+ ( \l__enumext_labelwidth_viii_dim + \l__enumext_labelsep_viii_dim )
+ / \l__enumext_columns_viii_int
+ }
+ }
+ \int_set:Nn \l__enumext_tmpa_viii_int { \l__enumext_columns_viii_int - 1 }
+ \dim_set:Nn \l__enumext_item_width_viii_dim
+ {
+ ( \linewidth - \l__enumext_columns_sep_viii_dim * \l__enumext_tmpa_viii_int )
+ / \l__enumext_columns_viii_int
+ - \l__enumext_labelwidth_viii_dim
+ - \l__enumext_labelsep_viii_dim
+ }
+ \dim_compare:nNnT { \l__enumext_rightmargin_viii_dim } > { \c_zero_dim }
+ {
+ \dim_sub:Nn \l__enumext_item_width_viii_dim
+ {
+ ( \l__enumext_rightmargin_viii_dim * \l__enumext_tmpa_vii_int )
+ / \l__enumext_columns_viii_int
+ }
+ \dim_add:Nn \l__enumext_columns_sep_viii_dim
+ {
+ \l__enumext_rightmargin_viii_dim
+ }
+ }
+ }
+%% Set width for joined item's for |enumext*| and |keyans*| environments.
+\cs_new_protected:Npn \__enumext_starred_joined_item_vii:n #1
+ {
+ \int_set:Nn \l__enumext_joined_item_vii_int {#1}
+ \int_compare:nNnT { \l__enumext_joined_item_vii_int } > { \l__enumext_columns_vii_int }
+ {
+ \msg_warning:nnee { enumext } { item-joined }
+ { \int_use:N \l__enumext_joined_item_vii_int }
+ { \int_use:N \l__enumext_columns_vii_int }
+ \int_set:Nn \l__enumext_joined_item_vii_int
+ {
+ \l__enumext_columns_vii_int - \l__enumext_item_column_pos_vii_int + 1
+ }
+ }
+ \int_compare:nNnT
+ { \l__enumext_joined_item_vii_int }
+ >
+ { \l__enumext_columns_vii_int - \l__enumext_item_column_pos_vii_int + 1 }
+ {
+ \msg_warning:nnee { enumext } { item-joined-columns }
+ { \int_use:N \l__enumext_joined_item_vii_int }
+ {
+ \int_eval:n
+ { \l__enumext_columns_vii_int - \l__enumext_item_column_pos_vii_int + 1 }
+ }
+ \int_set:Nn \l__enumext_joined_item_vii_int
+ {
+ \l__enumext_columns_vii_int - \l__enumext_item_column_pos_vii_int + 1
+ }
+ }
+ \int_compare:nNnTF { \l__enumext_joined_item_vii_int } > { 1 }
+ {
+ \int_set_eq:NN \l__enumext_joined_item_aux_vii_int \l__enumext_joined_item_vii_int
+ \int_decr:N \l__enumext_joined_item_aux_vii_int
+ \int_add:Nn \l__enumext_item_column_pos_vii_int { \l__enumext_joined_item_aux_vii_int }
+ \int_gadd:Nn \g__enumext_item_count_all_vii_int { \l__enumext_joined_item_aux_vii_int }
+ \dim_set:Nn \l__enumext_joined_width_vii_dim
+ {
+ \l__enumext_item_width_vii_dim * \l__enumext_joined_item_vii_int
+ + ( \l__enumext_labelwidth_vii_dim + \l__enumext_labelsep_vii_dim
+ + \l__enumext_columns_sep_vii_dim
+ )*\l__enumext_joined_item_aux_vii_int
+ }
+ \dim_set_eq:NN \itemwidth \l__enumext_joined_width_vii_dim
+ }
+ {
+ \dim_set_eq:NN \l__enumext_joined_width_vii_dim \l__enumext_item_width_vii_dim
+ \dim_set_eq:NN \itemwidth \l__enumext_item_width_vii_dim
+ }
+ }
+\cs_new_protected:Npn \__enumext_starred_joined_item_viii:n #1
+ {
+ \int_set:Nn \l__enumext_joined_item_viii_int {#1}
+ \int_compare:nNnT { \l__enumext_joined_item_viii_int } > { \l__enumext_columns_viii_int }
+ {
+ \msg_warning:nnee { enumext } { item-joined }
+ { \int_use:N \l__enumext_joined_item_viii_int }
+ { \int_use:N \l__enumext_columns_viii_int }
+ \int_set:Nn \l__enumext_joined_item_viii_int
+ {
+ \l__enumext_columns_viii_int - \l__enumext_item_column_pos_viii_int + 1
+ }
+ }
+ \int_compare:nNnT
+ { \l__enumext_joined_item_viii_int }
+ >
+ { \l__enumext_columns_viii_int - \l__enumext_item_column_pos_viii_int + 1 }
+ {
+ \msg_warning:nnee { enumext } { item-joined-columns }
+ { \int_use:N \l__enumext_joined_item_viii_int }
+ {
+ \int_eval:n
+ { \l__enumext_columns_viii_int - \l__enumext_item_column_pos_viii_int + 1 }
+ }
+ \int_set:Nn \l__enumext_joined_item_viii_int
+ {
+ \l__enumext_columns_viii_int - \l__enumext_item_column_pos_viii_int + 1
+ }
+ }
+ \int_compare:nNnTF { \l__enumext_joined_item_viii_int } > { 1 }
+ {
+ \int_set_eq:NN \l__enumext_joined_item_aux_viii_int \l__enumext_joined_item_viii_int
+ \int_decr:N \l__enumext_joined_item_aux_viii_int
+ \int_add:Nn \l__enumext_item_column_pos_viii_int { \l__enumext_joined_item_aux_viii_int }
+ \int_gadd:Nn \g__enumext_item_count_all_viii_int { \l__enumext_joined_item_aux_viii_int }
+ \dim_set:Nn \l__enumext_joined_width_viii_dim
+ {
+ \l__enumext_item_width_viii_dim * \l__enumext_joined_item_viii_int
+ + ( \l__enumext_labelwidth_viii_dim + \l__enumext_labelsep_viii_dim
+ + \l__enumext_columns_sep_viii_dim
+ )*\l__enumext_joined_item_aux_viii_int
+ }
+ \dim_set_eq:NN \itemwidth \l__enumext_joined_width_viii_dim
+ }
+ {
+ \dim_set_eq:NN \l__enumext_joined_width_viii_dim \l__enumext_item_width_viii_dim
+ \dim_set_eq:NN \itemwidth \l__enumext_item_width_viii_dim
+ }
+ }
+%% Start support for |mini-env| key in |enumext*| environment.
+\cs_new_protected:Nn \__enumext_start_mini_vii:
+ {
+ \dim_compare:nNnT { \l__enumext_minipage_right_vii_dim } > { \c_zero_dim }
+ {
+ \dim_set:Nn \l__enumext_minipage_left_vii_dim
+ {
+ \linewidth
+ - \l__enumext_minipage_right_vii_dim
+ - \l__enumext_minipage_hsep_vii_dim
+ }
+ \bool_set_true:N \l__enumext_minipage_active_vii_bool
+ \dim_gset_eq:NN
+ \g__enumext_minipage_right_vii_dim
+ \l__enumext_minipage_right_vii_dim
+ \__enumext_mini_addvspace_vii:
+ \nointerlineskip\noindent
+ \__enumext_mini_page{ \l__enumext_minipage_left_vii_dim }
+ }
+ }
+%% Stop support for |mini-env| key ans stop |list| in |enumext*| environment.
+\cs_new_protected:Nn \__enumext_stop_mini_vii:
+ {
+ \bool_if:NTF \l__enumext_minipage_active_vii_bool
+ {
+ \__enumext_stop_list:
+ \__enumext_stop_store_level_vii:
+ \IfDocumentMetadataTF { \tag_resume:n {enumext*} } { }
+ \end__enumext_mini_page
+ \hfill
+ \bool_gset_true:N \g__enumext_minipage_active_vii_bool
+ }
+ {
+ \__enumext_stop_list:
+ \__enumext_stop_store_level_vii:
+ }
+ }
+%% Exec |mini-right|, |mini-right*| keys in |enumext*| environment.
+\__enumext_after_env:nn {enumext*}
+ {
+ \bool_if:NT \g__enumext_minipage_active_vii_bool
+ {
+ \__enumext_minipage:w [ t ] { \g__enumext_minipage_right_vii_dim }
+ \legacy_if_gset_false:n { @minipage }
+ \skip_vertical:N \c_zero_skip
+ \par\addvspace { \g__enumext_minipage_right_skip }
+ \bool_if:NF \g__enumext_minipage_center_vii_bool
+ {
+ \tl_put_left:Nn \g__enumext_miniright_code_vii_tl
+ {
+ \centering
+ }
+ }
+ \vbox_set_top:Nn \l__enumext_miniright_code_vii_box
+ {
+ \tl_use:N \g__enumext_miniright_code_vii_tl
+ }
+ \box_use_drop:N \l__enumext_miniright_code_vii_box
+ \skip_vertical:N \c_zero_skip
+ \__enumext_endminipage:
+ \par\addvspace{ \g__enumext_minipage_after_skip }
+ }
+ \bool_gset_false:N \g__enumext_minipage_active_vii_bool
+ \bool_gset_true:N \g__enumext_minipage_center_vii_bool
+ \tl_gclear:N \g__enumext_miniright_code_vii_tl
+ \dim_gzero:N \g__enumext_minipage_right_vii_dim
+ \bool_gset_false:N \g__enumext_starred_bool
+ }
+%% Support for |mini-env|, |mini-right| and |mini-right*| key in |keyans*| environment.
+\cs_new_protected:Nn \__enumext_start_mini_viii:
+ {
+ \dim_compare:nNnT { \l__enumext_minipage_right_viii_dim } > { \c_zero_dim }
+ {
+ \dim_set:Nn \l__enumext_minipage_left_viii_dim
+ {
+ \linewidth
+ - \l__enumext_minipage_right_viii_dim
+ - \l__enumext_minipage_hsep_viii_dim
+ }
+ \bool_set_true:N \l__enumext_minipage_active_viii_bool
+ \dim_gset_eq:NN
+ \g__enumext_minipage_right_viii_dim
+ \l__enumext_minipage_right_viii_dim
+ \__enumext_mini_addvspace_viii:
+ \nointerlineskip\noindent
+ \__enumext_mini_page{ \l__enumext_minipage_left_viii_dim }
+ }
+ }
+\cs_new_protected:Nn \__enumext_stop_mini_viii:
+ {
+ \bool_if:NTF \l__enumext_minipage_active_viii_bool
+ {
+ \__enumext_stop_list:
+ \IfDocumentMetadataTF { \tag_resume:n {keyans*} } { }
+ \end__enumext_mini_page
+ \hfill
+ \bool_gset_true:N \g__enumext_minipage_active_viii_bool
+ }
+ {
+ \__enumext_stop_list:
+ }
+ }
+\__enumext_after_env:nn {keyans*}
+ {
+ \bool_if:NT \g__enumext_minipage_active_viii_bool
+ {
+ \__enumext_mini_page{ \g__enumext_minipage_right_viii_dim }
+ \par\addvspace { \g__enumext_minipage_right_skip }
+ \bool_if:NF \g__enumext_minipage_center_viii_bool
+ {
+ \tl_put_left:Nn \g__enumext_miniright_code_viii_tl
+ {
+ \centering
+ }
+ }
+ \vbox_set_top:Nn \l__enumext_miniright_code_viii_box
+ {
+ \tl_use:N \g__enumext_miniright_code_viii_tl
+ }
+ \box_use_drop:N \l__enumext_miniright_code_viii_box
+ \end__enumext_mini_page
+ \par\addvspace{ \g__enumext_minipage_after_skip }
+ }
+ \bool_gset_false:N \g__enumext_minipage_active_viii_bool
+ \bool_gset_true:N \g__enumext_minipage_center_viii_bool
+ \tl_gclear:N \g__enumext_miniright_code_viii_tl
+ \dim_gzero:N \g__enumext_minipage_right_viii_dim
+ }
+%% Define |enumext*|
+\NewDocumentEnvironment{enumext*}{ o }
+ {
+ \__enumext_safe_exec_vii:
+ \__enumext_parse_keys_vii:n {#1}
+ \__enumext_before_list_vii:
+ \__enumext_start_store_level_vii:
+ \__enumext_start_list:nn { }
+ {
+ \__enumext_list_arg_two_vii:
+ \__enumext_before_keys_exec_vii:
+ }
+ \IfDocumentMetadataTF { \tag_suspend:n {enumext*} } { }
+ \__enumext_starred_columns_set_vii:
+ \item[] \scan_stop:
+ \cs_set_eq:NN \__enumext_stop_item_tmp_vii: \__enumext_first_item_tmp_vii:
+ \cs_set_eq:NN \item \__enumext_start_item_tmp_vii:
+ \ignorespaces
+ }
+ {
+ \IfDocumentMetadataTF { \tag_struct_end:n {tag=text-unit} } { }
+ \__enumext_stop_item_tmp_vii:
+ \__enumext_remove_extra_parsep_vii:
+ \__enumext_after_list_vii:
+ }
+%% Safe exec for |enumext*| environment (set vars for storage system).
+\cs_new_protected:Nn \__enumext_safe_exec_vii:
+ {
+ \__enumext_is_not_nested:
+ \__enumext_internal_mini_page:
+ \int_incr:N \l__enumext_level_h_int
+ \int_compare:nNnT { \l__enumext_level_h_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { nested }
+ }
+ \int_compare:nNnT { \l__enumext_keyans_level_h_int } = { 1 }
+ {
+ \msg_error:nnn { enumext } { nested-horizontal } { keyans*}
+ }
+ \bool_set_true:N \l__enumext_starred_bool
+ \bool_set_false:N \l__enumext_standar_bool
+ \__enumext_is_on_first_level:
+ }
+%% Parse |key=val| and store keys for |enumext*| environment.
+\cs_new_protected:Npn \__enumext_parse_keys_vii:n #1
+ {
+ \tl_if_novalue:nF {#1}
+ {
+ \str_clear:N \l__enumext_series_str
+ \keys_set:nn { enumext / enumext* } {#1}
+ \__enumext_parse_series:n {#1}
+ \__enumext_store_active_keys_vii:n {#1}
+ }
+ }
+\cs_new_protected:Nn \__enumext_before_list_vii:
+ {
+ \__enumext_vspace_above_vii:
+ \__enumext_check_ans_active:
+ \__enumext_before_args_exec_vii:
+ \__enumext_start_mini_vii:
+ }
+\cs_new_protected:Nn \__enumext_after_list_vii:
+ {
+ \__enumext_stop_mini_vii:
+ \__enumext_after_stop_list_vii:
+ \__enumext_check_ans_key_hook:
+ \__enumext_vspace_below_vii:
+ \bool_set_false:N \l__enumext_starred_bool
+ \__enumext_resume_save_counter:
+ }
+\cs_new_protected:Nn \__enumext_start_store_level_vii:
+ {
+ \bool_if:NT \l__enumext_store_active_bool
+ {
+ \int_compare:nNnT { \l__enumext_level_int } > { 0 }
+ {
+ \__enumext_store_level_open_vii:
+ }
+ }
+ }
+\cs_new_protected:Nn \__enumext_stop_store_level_vii:
+ {
+ \bool_if:NT \l__enumext_store_active_bool
+ {
+ \int_compare:nNnT { \l__enumext_level_int } > { 0 }
+ {
+ \__enumext_store_level_close_vii:
+ }
+ }
+ }
+%% Remove |\labelwidth+\labelsep| on left in first |\item| for |enumext*| environment.
+\cs_new_protected_nopar:Nn \__enumext_first_item_tmp_vii:
+ {
+ \skip_horizontal:n
+ {
+ -\l__enumext_labelwidth_vii_dim - \l__enumext_labelsep_vii_dim
+ }
+ \ignorespaces
+ }
+%% Start boxed item's for |enumext*| environment.
+\cs_new_protected_nopar:Nn \__enumext_start_item_tmp_vii:
+ {
+ \__enumext_stop_item_tmp_vii:
+ \int_incr:N \l__enumext_item_column_pos_vii_int
+ \int_gincr:N \g__enumext_item_count_all_vii_int
+ \__enumext_item_peek_args_vii:
+ }
+%% Peek argument for \item()*[][] for |enumext*| environment.
+\cs_new_protected:Nn \__enumext_item_peek_args_vii:
+ {
+ \peek_meaning:NTF (
+ { \__enumext_joined_item_vii:w }
+ { \__enumext_joined_item_vii:w (1) }
+ }
+%% Joined item's for |enumext*| environment.
+\cs_new_protected:Npn \__enumext_joined_item_vii:w (#1)
+ {
+ \__enumext_starred_joined_item_vii:n {#1}
+ \peek_meaning_remove:NTF *
+ { \__enumext_starred_item_vii:w }
+ { \__enumext_standar_item_vii:w }
+ }
+%% Set \item[opt] for |enumext*| environment.
+\cs_new_protected:Npn \__enumext_standar_item_vii:w
+ {
+ \bool_set_false:N \l__enumext_item_starred_vii_bool
+ \peek_meaning:NTF [
+ {
+ \bool_set_eq:NN \l__enumext_wrap_label_vii_bool \l__enumext_wrap_label_opt_vii_bool
+ \__enumext_start_item_vii:w
+ }
+ {
+ \bool_set_true:N \l__enumext_wrap_label_vii_bool
+ \legacy_if_set_true:n { @noitemarg }
+ \__enumext_start_item_vii:w [ \l__enumext_label_vii_tl ] \ignorespaces
+ }
+ }
+%% Set \item*[sym][sep] for |enumext*| environment.
+\cs_new_protected:Npn \__enumext_starred_item_vii:w
+ {
+ \bool_set_true:N \l__enumext_item_starred_vii_bool
+ \bool_set_true:N \l__enumext_wrap_label_vii_bool
+ \peek_meaning:NTF [
+ { \__enumext_starred_item_vii_aux_i:w }
+ { \__enumext_starred_item_vii_aux_ii:w }
+ }
+\cs_new_protected:Npn \__enumext_starred_item_vii_aux_i:w [#1]
+ {
+ \tl_gset:Nn \g__enumext_item_symbol_aux_vii_tl {#1}
+ \__enumext_starred_item_vii_aux_ii:w
+ }
+\cs_new_protected:Npn \__enumext_starred_item_vii_aux_ii:w
+ {
+ \peek_meaning:NTF [
+ { \__enumext_starred_item_vii_aux_iii:w }
+ {
+ \dim_set_eq:NN \l__enumext_item_symbol_sep_vii_dim \l__enumext_labelsep_vii_dim
+ \legacy_if_set_true:n { @noitemarg }
+ \__enumext_start_item_vii:w [ \l__enumext_label_vii_tl ] \ignorespaces
+ }
+ }
+\cs_new_protected:Npn \__enumext_starred_item_vii_aux_iii:w [#1]
+ {
+ \dim_set:Nn \l__enumext_item_symbol_sep_vii_dim {#1}
+ \legacy_if_set_true:n { @noitemarg }
+ \__enumext_start_item_vii:w [ \l__enumext_label_vii_tl ] \ignorespaces
+ }
+%% Fake \makelabel definition for |enumext*| environment.
+\cs_new_protected_nopar:Npn \__enumext_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__enumext_hyperref_bool
+ {
+ \legacy_if_set_true:n { @hyper@item }
+ }
+ } { }
+ \refstepcounter{enumXvii}
+ \bool_if:NT \l__enumext_check_answers_bool
+ {
+ \int_gincr:N \g__enumext_item_number_int
+ \bool_set_true:N \l__enumext_item_number_bool
+ }
+ }
+ }
+ \bool_if:NT \l__enumext_item_starred_vii_bool
+ {
+ \tl_if_blank:VT \g__enumext_item_symbol_aux_vii_tl
+ {
+ \tl_gset_eq:NN
+ \g__enumext_item_symbol_aux_vii_tl \l__enumext_item_symbol_vii_tl
+ }
+ \mode_leave_vertical:
+ \skip_horizontal:n { -\l__enumext_item_symbol_sep_vii_dim }
+ \hbox_overlap_left:n { \g__enumext_item_symbol_aux_vii_tl }
+ \skip_horizontal:N \l__enumext_item_symbol_sep_vii_dim
+ \tl_gclear:N \g__enumext_item_symbol_aux_vii_tl
+ }
+ \makebox[ \l__enumext_labelwidth_vii_dim ][ \l__enumext_align_label_vii_str ]
+ {
+ \tl_use:N \l__enumext_label_font_style_vii_tl
+ \bool_if:NTF \l__enumext_wrap_label_vii_bool
+ {
+ \__enumext_wrapper_label_vii:n {#1}
+ }
+ { #1 }
+ }
+ \skip_horizontal:N \l__enumext_labelsep_vii_dim \ignorespaces
+ }
+\cs_new_protected_nopar:Npn \__enumext_start_item_vii:w [#1]
+ {
+ \cs_set_eq:NN \__enumext_stop_item_tmp_vii: \__enumext_stop_item_vii:
+ \hbox_set_to_wd:Nnw \l__enumext_item_text_vii_box
+ {
+ \l__enumext_joined_width_vii_dim
+ + \l__enumext_labelwidth_vii_dim
+ + \l__enumext_labelsep_vii_dim
+ }
+ \__enumext_renew_footnote_starred:
+ \__enumext_start_list_tag:n {enumext*}
+ \__enumext_fake_make_label_vii:n {#1}
+ \__enumext_stop_start_list_tag:
+ \__enumext_minipage:w [ t ]{ \l__enumext_joined_width_vii_dim }
+ \dim_set_eq:NN \parindent \l__enumext_listparindent_vii_dim
+ \skip_set_eq:NN \parskip \l__enumext_parsep_vii_skip
+ \__enumext_unskip_unkern:
+ \__enumext_unskip_unkern:
+ \skip_horizontal:n { -\l__enumext_listparindent_vii_dim } \ignorespaces
+ \tl_use:N \l__enumext_fake_item_indent_vii_tl
+ \tl_use:N \l__enumext_after_list_args_vii_tl
+ }
+\cs_new_protected_nopar:Nn \__enumext_stop_item_vii:
+ {
+ \__enumext_endminipage:
+ \__enumext_stop_list_tag:n {enumext*}
+ \hbox_set_end:
+ \int_set:Nn \hbadness { 10000 }
+ \box_use_drop:N \l__enumext_item_text_vii_box
+ \int_compare:nNnTF
+ { \l__enumext_item_column_pos_vii_int } = { \l__enumext_columns_vii_int }
+ {
+ \par\noindent
+ \int_zero:N \l__enumext_item_column_pos_vii_int
+ }
+ {
+ \skip_horizontal:N \l__enumext_columns_sep_vii_dim
+ }
+ }
+%% Remove extra \parsep in |enumext*| environment.
+\cs_new_protected:Nn \__enumext_remove_extra_parsep_vii:
+ {
+ \int_compare:nNnT
+ {
+ \int_mod:nn
+ { \g__enumext_item_count_all_vii_int } { \l__enumext_columns_vii_int }
+ }
+ =
+ { 0 }
+ {
+ \para_end:
+ \skip_vertical:n { -\l__enumext_itemsep_vii_skip }
+ \skip_vertical:N \c_zero_skip
+ \int_gzero:N \g__enumext_item_count_all_vii_int
+ }
+ }
+%% Execute |check-ans| key out of |enumext*| environment.
+\__enumext_after_env:nn {enumext*}
+ {
+ \__enumext_execute_after_env:
+ }
+%% Define |keyans*| environment.
+\NewDocumentEnvironment{keyans*}{ o }
+ {
+ \__enumext_safe_exec_viii:
+ \__enumext_parse_keys_viii:n {#1}
+ \__enumext_before_list_viii:
+ \__enumext_start_list:nn { }
+ {
+ \__enumext_list_arg_two_viii:
+ \__enumext_before_keys_exec_viii:
+ }
+ \IfDocumentMetadataTF { \tag_suspend:n {keyans*} } { }
+ \__enumext_starred_columns_set_viii:
+ \item[] \scan_stop:
+ \cs_set_eq:NN \__enumext_stop_item_tmp_viii: \__enumext_first_item_tmp_viii:
+ \cs_set_eq:NN \item \__enumext_start_item_tmp_viii:
+ \ignorespaces
+ }
+ {
+ \IfDocumentMetadataTF { \tag_struct_end:n {tag=text-unit} } { }
+ \__enumext_stop_item_tmp_viii:
+ \__enumext_remove_extra_parsep_viii:
+ \__enumext_check_starred_cmd:n { item }
+ \__enumext_after_list_viii:
+ }
+%% Test deep-level for |keyans*| environment and set bool vars.
+\cs_new_protected:Nn \__enumext_safe_exec_viii:
+ {
+ \bool_if:NF \l__enumext_store_active_bool
+ {
+ \msg_error:nnnn { enumext } { wrong-place }{ keyans* }{ save-ans }
+ }
+ \int_incr:N \l__enumext_keyans_level_h_int
+ \int_compare:nNnT { \l__enumext_keyans_level_h_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { nested }
+ }
+ \__enumext_keyans_name_and_start:
+ \bool_if:NT \l__enumext_starred_bool
+ {
+ \msg_error:nnn { enumext } { nested-horizontal } { enumext* }
+ }
+ \bool_set_true:N \l__enumext_starred_bool
+ % Set false for interfering with enumext nested in keyans* (yes, its possible and crayze)
+ \bool_set_false:N \l__enumext_store_active_bool
+ \int_compare:nNnT { \l__enumext_level_int } > { 1 }
+ {
+ \msg_error:nn { enumext } { keyans-wrong-level }
+ }
+ }
+%% Parse |key=val| and store keys for |keyans*| environment.
+\cs_new_protected:Npn \__enumext_parse_keys_viii:n #1
+ {
+ \tl_if_novalue:nF {#1}
+ {
+ \keys_set:nn { enumext / keyans* } {#1}
+ }
+ }
+\cs_new_protected:Nn \__enumext_before_list_viii:
+ {
+ \__enumext_vspace_above_viii:
+ \__enumext_before_args_exec_viii:
+ \__enumext_start_mini_viii:
+ }
+\cs_new_protected:Nn \__enumext_after_list_viii:
+ {
+ \__enumext_stop_mini_viii:
+ \__enumext_after_stop_list_viii:
+ \__enumext_vspace_below_viii:
+ }
+%% Remove |\labelwidth+\labelsep| on left in first |\item| for |keyans*| environment.
+\cs_new_protected_nopar:Nn \__enumext_first_item_tmp_viii:
+ {
+ \skip_horizontal:n
+ {
+ -\l__enumext_labelwidth_viii_dim - \l__enumext_labelsep_viii_dim
+ }
+ \ignorespaces
+ }
+%% Start boxed item's for |keyans*| environment.
+\cs_new_protected_nopar:Nn \__enumext_start_item_tmp_viii:
+ {
+ \__enumext_stop_item_tmp_viii:
+ \int_incr:N \l__enumext_item_column_pos_viii_int
+ \int_gincr:N \g__enumext_item_count_all_viii_int
+ \__enumext_item_peek_args_viii:
+ }
+%% Peek argument for \item(number)*[opt] for |keyans*| environment.
+\cs_new_protected:Nn \__enumext_item_peek_args_viii:
+ {
+ \peek_meaning:NTF (
+ { \__enumext_joined_item_viii:w }
+ { \__enumext_joined_item_viii:w (1) }
+ }
+%% Joined item's for |keyans*| environment.
+\cs_new_protected:Npn \__enumext_joined_item_viii:w (#1)
+ {
+ \__enumext_starred_joined_item_viii:n {#1}
+ \peek_meaning_remove:NTF *
+ { \__enumext_starred_item_viii:w }
+ { \__enumext_standar_item_viii:w }
+ }
+%% Set standard \item[opt] for |keyans*| environment.
+\cs_new_protected:Npn \__enumext_standar_item_viii:w
+ {
+ \bool_set_false:N \l__enumext_item_starred_viii_bool
+ \peek_meaning:NTF [
+ {
+ \bool_set_eq:NN \l__enumext_wrap_label_viii_bool \l__enumext_wrap_label_opt_viii_bool
+ \__enumext_start_item_viii:w
+ }
+ {
+ \bool_set_true:N \l__enumext_wrap_label_viii_bool
+ \legacy_if_set_true:n { @noitemarg }
+ \__enumext_start_item_viii:w [ \l__enumext_label_viii_tl ] \ignorespaces
+ }
+ }
+%% Set \item*[content] for |keyans*| environment.
+\cs_new_protected:Npn \__enumext_starred_item_viii:w
+ {
+ \bool_set_true:N \l__enumext_item_starred_viii_bool
+ \bool_set_true:N \l__enumext_wrap_label_viii_bool
+ \peek_meaning:NTF [
+ { \__enumext_starred_item_viii_aux_i:w }
+ { \__enumext_starred_item_viii_aux_ii:w }
+ }
+\cs_new_protected:Npn \__enumext_starred_item_viii_aux_i:w [#1]
+ {
+ \tl_clear:N \l__enumext_store_current_label_tl
+ \tl_if_novalue:nF { #1 }
+ {
+ \tl_if_empty:NF \l__enumext_store_keyans_item_opt_sep_tl
+ {
+ \tl_put_right:Ne \l__enumext_store_current_label_tl
+ {
+ \l__enumext_store_keyans_item_opt_sep_tl
+ }
+ \tl_put_right:Ne \l__enumext_store_current_label_tl { #1 }
+ }
+ \tl_set:Ne \l__enumext_store_current_opt_arg_tl { #1 }
+ }
+ \__enumext_starred_item_viii_aux_ii:w
+ }
+\cs_new_protected:Npn \__enumext_starred_item_viii_aux_ii:w
+ {
+ \legacy_if_set_true:n { @noitemarg }
+ \__enumext_start_item_viii:w [ \l__enumext_label_viii_tl ] \ignorespaces
+ }
+%% Set \item*[content] for |keyans*| environment.
+\cs_new_protected:Nn \__enumext_starred_item_exec:
+ {
+ \tl_put_left:Ne \l__enumext_store_current_label_tl { \l__enumext_label_viii_tl }
+ \__enumext_store_addto_prop:V \l__enumext_store_current_label_tl
+ \__enumext_keyans_store_ref:
+ \tl_put_left:Ne \l__enumext_store_current_label_tl { \item }
+ \__enumext_keyans_addto_seq_link:
+ \int_gincr:N \g__enumext_check_starred_cmd_int
+ \bool_if:NT \l__enumext_show_answer_bool
+ {
+ \__enumext_print_keyans_box:NN \l__enumext_labelwidth_i_dim \l__enumext_labelsep_i_dim
+ }
+ \bool_if:NT \l__enumext_show_position_bool
+ {
+ \tl_set:Ne \l__enumext_mark_answer_sym_tl
+ {
+ \group_begin:
+ \exp_not:N \normalfont
+ \exp_not:N \footnotesize [ \int_eval:n
+ {
+ \prop_count:c { g__enumext_ \l__enumext_store_name_tl _prop }
+ }
+ ]
+ \group_end:
+ }
+ \__enumext_print_keyans_box:NN \l__enumext_labelwidth_i_dim \l__enumext_labelsep_i_dim
+ }
+ }
+%% Define a fake |\makelabel| for |keyans*| environment.
+\cs_new_protected_nopar:Npn \__enumext_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__enumext_item_starred_viii_bool
+ {
+ \__enumext_starred_item_exec:
+ }
+ \makebox[ \l__enumext_labelwidth_viii_dim ][ \l__enumext_align_label_viii_str ]
+ {
+ \tl_use:N \l__enumext_label_font_style_viii_tl
+ \bool_if:NTF \l__enumext_wrap_label_viii_bool
+ {
+ \__enumext_wrapper_label_viii:n {#1}
+ }
+ { #1 }
+ }
+ \skip_horizontal:N \l__enumext_labelsep_viii_dim \ignorespaces
+ }
+%% Real |\item| definition for |keyans*| environment.
+\cs_new_protected_nopar:Npn \__enumext_start_item_viii:w [#1]
+ {
+ \cs_set_eq:NN \__enumext_stop_item_tmp_viii: \__enumext_stop_item_viii:
+ \hbox_set_to_wd:Nnw \l__enumext_item_text_viii_box
+ {
+ \l__enumext_joined_width_viii_dim
+ + \l__enumext_labelwidth_viii_dim
+ + \l__enumext_labelsep_viii_dim
+ }
+ \__enumext_renew_footnote_starred:
+ \__enumext_start_list_tag:n {keyans*}
+ \__enumext_fake_make_label_viii:n {#1}
+ \__enumext_stop_start_list_tag:
+ \__enumext_minipage:w [ t ]{ \l__enumext_joined_width_viii_dim }
+ \dim_set_eq:NN \parindent \l__enumext_listparindent_viii_dim
+ \skip_set_eq:NN \parskip \l__enumext_parsep_viii_skip
+ \__enumext_unskip_unkern:
+ \__enumext_unskip_unkern:
+ \skip_horizontal:n { -\l__enumext_listparindent_viii_dim } \ignorespaces
+ \tl_use:N \l__enumext_fake_item_indent_viii_tl
+ \bool_if:NT \l__enumext_item_starred_viii_bool
+ {
+ \__enumext_keyans_show_item_opt:
+ }
+ \tl_use:N \l__enumext_after_list_args_viii_tl
+ }
+\cs_new_protected_nopar:Nn \__enumext_stop_item_viii:
+ {
+ \__enumext_endminipage:
+ \__enumext_stop_list_tag:n {keyans*}
+ \hbox_set_end:
+ \int_set:Nn \hbadness { 10000 }
+ \box_use_drop:N \l__enumext_item_text_viii_box
+ \int_compare:nNnTF
+ { \l__enumext_item_column_pos_viii_int } = { \l__enumext_columns_viii_int }
+ {
+ \par\noindent
+ \int_zero:N \l__enumext_item_column_pos_viii_int
+ }
+ {
+ \skip_horizontal:N \l__enumext_columns_sep_viii_dim
+ }
+ }
+%% Remove extra \parsep in |keyans*| environment.
+\cs_new_protected:Nn \__enumext_remove_extra_parsep_viii:
+ {
+ \int_compare:nNnT
+ {
+ \int_mod:nn
+ { \g__enumext_item_count_all_viii_int }
+ { \l__enumext_columns_viii_int }
+ }
+ =
+ { 0 }
+ {
+ \para_end:
+ \skip_vertical:n { -\l__enumext_itemsep_viii_skip }
+ \skip_vertical:N \c_zero_skip
+ \int_gzero:N \g__enumext_item_count_all_viii_int
+ }
+ }
+%% Define |\getkeyans|.
+\NewDocumentCommand \getkeyans { m }
+ {
+ \exp_args:Ne \__enumext_getkeyans_aux:n
+ { \tl_to_str:e { \text_expand:n {#1} } }
+ }
+%% Internal functions for |\getkeyans|.
+\cs_new_protected:Npn \__enumext_getkeyans_aux:n #1
+ {
+ \str_if_in:nnTF {#1} { : }
+ {
+ \use:e
+ {
+ \cs_set:Npn \exp_not:N \__enumext_tmp:w ##1 \c_colon_str ##2 \scan_stop:
+ { {##1} {##2} }
+ }
+ \exp_after:wN \__enumext_getkeyans:nn \__enumext_tmp:w #1 \scan_stop:
+ }
+ { \msg_error:nnn { enumext } { missing-colon } {#1} }
+ }
+\cs_new_protected:Npn \__enumext_getkeyans:nn #1 #2
+ {
+ \prop_if_exist:cTF { g__enumext_#1_prop }
+ {
+ \prop_item:cn { g__enumext_#1_prop }{#2}
+ }
+ {
+ \msg_error:nnn { enumext } { undefined-storage-anskey } {#1}
+ }
+ }
+%% Add keys for |\printkeyans|.
+\keys_define:nn { enumext / print }
+ {
+ print* .code:n = \keys_precompile:neN { enumext / enumext* }
+ { \__enumext_filter_save_key:n {#1} }
+ \l__enumext_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 }
+ { \__enumext_filter_save_key:n {#1} }
+ \l__enumext_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 }
+ { \__enumext_filter_save_key:n {#1} }
+ \l__enumext_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 }
+ { \__enumext_filter_save_key:n {#1} }
+ \l__enumext_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 }
+ { \__enumext_filter_save_key:n {#1} }
+ \l__enumext_print_keyans_iv_tl,
+ print-4 .initial:n = { nosep, label=\Alph*., first=\small, font=\small },
+ print-* .code:n = \keys_precompile:neN { enumext / enumext* }
+ { \__enumext_filter_save_key:n {#1} }
+ \l__enumext_print_keyans_vii_tl, % starred nested
+ print-* .initial:n = { nosep, label=\arabic*., first=\small, font=\small },
+ }
+%% Define |\printkeyans|.
+\NewDocumentCommand \printkeyans { s O{} m }
+ {
+ \group_begin:
+ \tl_use:N \l__enumext_print_keyans_i_tl
+ \tl_use:N \l__enumext_print_keyans_ii_tl
+ \tl_use:N \l__enumext_print_keyans_iii_tl
+ \tl_use:N \l__enumext_print_keyans_iv_tl
+ \tl_use:N \l__enumext_print_keyans_vii_tl
+ \__enumext_printkeyans:nnn { #1 } { #2 } { #3 }
+ \group_end:
+ }
+%% Internal function for |\printkeyans|.
+\cs_new_protected:Npn \__enumext_printkeyans:nnn #1 #2 #3
+ {
+ \seq_if_exist:cTF { g__enumext_#3_seq }
+ {
+ \seq_if_empty:cF { g__enumext_#3_seq }
+ {
+ \bool_if:nTF {#1}
+ {
+ \seq_if_in:cnTF { g__enumext_#3_seq } { \end{enumext*} }
+ {
+ \msg_error:nnnn { enumext } { print-starred } {#3} { enumext* }
+ }
+ {
+ \tl_use:N \l__enumext_print_keyans_starred_tl
+ \bool_set_true:N \l__enumext_base_line_fix_bool
+ \bool_set_true:N \l__enumext_print_keyans_star_bool
+ \begin{enumext*}[#2]
+ \seq_map_inline:cn { g__enumext_#3_seq } { ##1 }
+ \end{enumext*}
+ \bool_set_false:N \l__enumext_base_line_fix_bool
+ \bool_set_false:N \l__enumext_print_keyans_star_bool
+ }
+ }
+ {
+ \begin{enumext}[#2]
+ \seq_map_inline:cn { g__enumext_#3_seq } { ##1 }
+ \end{enumext}
+ }
+ }
+ }
+ {
+ \msg_error:nnn { enumext } { undefined-storage-anskey } {#3}
+ }
+ }
+%% Internal function for filter keys in |\setenumext| for first level.
+\cs_new:Npn \__enumext_filter_first_level:n #1
+ {
+ \use:e
+ {
+ \keyval_parse:NNn
+ \__enumext_filter_first_level_key:n
+ \__enumext_filter_first_level_pair:nn {#1}
+ }
+ }
+\cs_new:Npn \__enumext_filter_first_level_key:n #1
+ {
+ \str_case:nnF {#1}
+ {
+ { resume } {}
+ { resume* } {}
+ }
+ { , { \exp_not:n {#1} } }
+ }
+\cs_new:Npn \__enumext_filter_first_level_pair:nn #1#2
+ {
+ \str_case:nnF {#1}
+ {
+ { series } {}
+ { resume } {}
+ { save-ans } {}
+ }
+ { , { \exp_not:n {#1} } = { \exp_not:n {#2} } }
+ }
+%% Add keys for |\setenumext|.
+\keys_define:nn { enumext / meta-families }
+ {
+ enumext-1 .code:n =
+ {
+ \keys_set:ne { enumext / level-1 }
+ {
+ \__enumext_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* }
+ {
+ \__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 } } ,
+ }
+\seq_const_from_clist:Nn \c__enumext_all_families_seq
+ {
+ enumext-1, enumext-2, enumext-3, enumext-4, keyans, enumext*,
+ keyans*, print-1, print-2, print-3, print-4, print-*, print*,
+ }
+%% Define |\setenumext|.
+\NewDocumentCommand \setenumext { O{enumext,1} +m }
+ {
+ \seq_clear:N \l__enumext_setkey_tmpa_seq
+ \seq_set_from_clist:Nn \l__enumext_setkey_tmpb_seq {#1}
+ \int_set:Nn \l__enumext_setkey_tmpa_int
+ {
+ \seq_count:N \l__enumext_setkey_tmpb_seq
+ }
+ \int_compare:nNnTF { \l__enumext_setkey_tmpa_int } > { 1 }
+ {
+ \seq_pop_left:NN \l__enumext_setkey_tmpb_seq \l__enumext_setkey_tmpa_tl
+ \seq_map_function:NN \l__enumext_setkey_tmpb_seq \__enumext_set_parse:n
+ \seq_set_map_e:NNn \l__enumext_setkey_tmpa_seq \l__enumext_setkey_tmpa_seq
+ {
+ \tl_use:N \l__enumext_setkey_tmpa_tl - ##1
+ }
+ }
+ {
+ \seq_put_right:Ne \l__enumext_setkey_tmpa_seq { \tl_trim_spaces:n {#1} }
+ }
+ \seq_if_empty:NTF \l__enumext_setkey_tmpa_seq
+ { \seq_map_inline:Nn \c__enumext_all_families_seq }
+ { \seq_map_inline:Nn \l__enumext_setkey_tmpa_seq }
+ {
+ \keys_set:nn { enumext / meta-families } { ##1 = {#2} }
+ }
+ }
+\cs_new_protected:Npn \__enumext_set_parse:n #1
+ {
+ \tl_set:Ne \l__enumext_setkey_tmpb_tl { \tl_trim_spaces:n {#1} }
+ \clist_map_inline:nn { 0, 1, 2, 3, 4, * } % <- max level
+ { \tl_remove_all:Nn \l__enumext_setkey_tmpb_tl {##1} }
+ \tl_if_empty:NTF \l__enumext_setkey_tmpb_tl
+ {
+ \seq_put_right:Ne \l__enumext_setkey_tmpa_seq
+ { \tl_trim_spaces:n {#1} }
+ }
+ { \__enumext_set_error:nn {#1} { } }
+ }
+\cs_new_protected:Npn \__enumext_set_error:nn #1 #2
+ { \msg_error:nnn { enumext } { invalid-key } {#1} {#2} }
+%% Define |\setenumextmeta|.
+\prop_const_from_keyval:Nn \c__enumext_meta_paths_prop
+ {
+ {enumext,1} = level-1,
+ {enumext,2} = level-2,
+ {enumext,3} = level-3,
+ {enumext,4} = level-4,
+ {enumext*} = enumext*
+ }
+\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 }
+ { \__enumext_add_meta_key:nnn { enumext, ##1 } {#3} {#4} }
+ \__enumext_add_meta_key:nnn { enumext* } {#3} {#4}
+ }
+ { \__enumext_add_meta_key:nnn {#2} {#3} {#4} }
+ }
+ }
+\cs_new_protected:Npn \__enumext_add_meta_key:nnn #1
+ {
+ \tl_set:Nn \l__enumext_meta_path_tl {#1}
+ \tl_replace_all:Nnn \l__enumext_meta_path_tl { ~ } {}
+ \prop_get:NVNTF
+ \c__enumext_meta_paths_prop \l__enumext_meta_path_tl \l__enumext_meta_path_tl
+ { \__enumext_def_meta_key:Vnn \l__enumext_meta_path_tl }
+ {
+ \msg_error:nnn { enumext } { unknown-set } {#1}
+ \use_none:nn
+ }
+ }
+\cs_new_protected:Npn \__enumext_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 \__enumext_def_meta_key:nnn { V }
+%% Define |\foreachkeyans|.
+\keys_define:nn { enumext / foreach }
+ {
+ before .tl_set:N = \l__enumext_foreach_before_tl,
+ before .value_required:n = true,
+ after .tl_set:N = \l__enumext_foreach_after_tl,
+ after .value_required:n = true,
+ start .int_set:N = \l__enumext_foreach_start_int,
+ start .value_required:n = true,
+ stop .int_set:N = \l__enumext_foreach_stop_int,
+ stop .value_required:n = true,
+ step .int_set:N = \l__enumext_foreach_step_int,
+ step .value_required:n = true,
+ wrapper .cs_set_protected:Np = \__enumext_foreach_wrapper:n #1,
+ wrapper .value_required:n = true,
+ sep .tl_set:N = \l__enumext_foreach_sep_tl,
+ sep .value_required:n = true,
+ unknown .code:n = { \__enumext_parse_foreach_keys:n {#1} }
+ }
+\keys_precompile:nnN { enumext / foreach }
+ {
+ before={},after={},start=1,step=1,stop=0,wrapper=#1,sep={; }
+ }
+ \g__enumext_foreach_default_keys_tl
+\cs_new_protected:Npn \__enumext_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 \__enumext_parse_foreach_keys:n #1
+ {
+ \exp_args:NV \__enumext_parse_foreach_keys:nn \l_keys_key_str {#1}
+ }
+\NewDocumentCommand \foreachkeyans { +O{} m }
+ {
+ \__enumext_foreach_keyans:nn {#1} {#2}
+ }
+\cs_new_protected:Npn \__enumext_foreach_keyans:nn #1 #2
+ {
+ \tl_use:N \g__enumext_foreach_default_keys_tl
+ \keys_set:nn { enumext / foreach } {#1}
+ \tl_set:Nn \l__enumext_foreach_name_prop_tl {#2}
+ \prop_if_exist:cF { g__enumext_#2_prop }
+ {
+ \msg_error:nnn { enumext } { undefined-storage-anskey } {#2}
+ }
+ \int_compare:nNnT { \l__enumext_foreach_stop_int } = { 0 }
+ {
+ \int_set:Nn \l__enumext_foreach_stop_int
+ { \prop_count:c { g__enumext_#2_prop } }
+ }
+ \seq_clear:N \l__enumext_foreach_print_seq
+ \int_step_function:nnnN
+ { \l__enumext_foreach_start_int }
+ { \l__enumext_foreach_step_int }
+ { \l__enumext_foreach_stop_int }
+ \__enumext_foreach_add_body:n
+ \seq_use:NV \l__enumext_foreach_print_seq \l__enumext_foreach_sep_tl
+ }
+\cs_new_protected:Npn \__enumext_foreach_add_body:n #1
+ {
+ \seq_put_right:Ne \l__enumext_foreach_print_seq
+ {
+ \exp_not:V \l__enumext_foreach_before_tl
+ \__enumext_foreach_wrapper:n
+ {
+ \prop_item:cn { g__enumext_ \l__enumext_foreach_name_prop_tl _prop }{#1}
+ }
+ \exp_not:V \l__enumext_foreach_after_tl
+ }
+ }
+%% Messages.
+\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'.
+ }
+\msg_new:nnn { enumext } { counters }
+ {
+ The ~ counter ~ '#1' ~ is ~ already ~ defined ~ by ~ some ~ \\
+ package ~ or ~ macro, ~ it ~ cannot ~ be ~ continued.
+ }
+\msg_new:nnn { enumext } { unknown-choice }
+ {
+ The ~ value ~ '#3' ~ for ~ '#1' ~ key ~ is ~ invalid ~ use ~ ('#2').
+ }
+\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.\\
+ }
+\msg_new:nnn { enumext } { store-prop }
+ {
+ * ~ Package ~ enumext: ~ Creating ~
+ \c_backslash_str g__enumext_#1_prop ~ \msg_line_context:.
+ }
+\msg_new:nnn { enumext } { store-seq }
+ {
+ * ~ Package ~ enumext: ~ Creating ~
+ \c_backslash_str g__enumext_#1_seq ~ \msg_line_context:.
+ }
+\msg_new:nnn { enumext } { store-int }
+ {
+ * ~ Package ~ enumext: ~ Creating ~
+ \c_backslash_str g__enumext_resume_#1_int ~ \msg_line_context:.
+ }
+\msg_new:nnn { enumext } { prop-seq-int-hook }
+ {
+ * ~ Package ~ enumext: ~ Elements ~ in ~
+ \c_backslash_str g__enumext_#1_prop ~ = ~ #2.\\
+ * ~ Package ~ enumext: ~ Elements ~ in ~
+ \c_backslash_str g__enumext_#1_seq ~ = ~ #3.\\
+ * ~ Package ~ enumext: ~ Value ~ off ~
+ \c_backslash_str g__enumext_resume_#1_int ~ = ~ #4.
+ }
+\msg_new:nnn { enumext } { item-answer-hook }
+ {
+ * ~ Package ~ enumext: ~ Value ~ off ~
+ \c_backslash_str g__enumext_item_number_int ~ = ~ #1.\\
+ * ~ Package ~ enumext: ~ Value ~ off ~
+ \c_backslash_str g__enumext_item_anskey_int ~ = ~ #2.\\
+ * ~ Package ~ enumext: ~ Difference ~ item_number_int ~ - ~ item_anskey_int ~ = ~ #3.
+ }
+\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.
+ }
+\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.
+ }
+\msg_new:nnn { enumext } { list-lengths }
+ {
+ **** ~ Lengths ~ used ~ by ~ 'enumext' ~ level ~ '#2' ~ \msg_line_context:~\c_space_tl ****\\
+ \__enumext_show_length:nnn { dim } { labelsep } {#1}
+ \__enumext_show_length:nnn { dim } { labelwidth } {#1}
+ \__enumext_show_length:nnn { dim } { itemindent } {#1}
+ \__enumext_show_length:nnn { dim } { leftmargin } {#1}
+ \__enumext_show_length:nnn { dim } { rightmargin } {#1}
+ \__enumext_show_length:nnn { dim } { listparindent } {#1}
+ \__enumext_show_length:nnn { skip } { topsep } {#1}
+ \__enumext_show_length:nnn { skip } { parsep } {#1}
+ \__enumext_show_length:nnn { skip } { partopsep } {#1}
+ \__enumext_show_length:nnn { skip } { itemsep } {#1}
+ ****************************************************
+ }
+\msg_new:nnn { enumext } { list-lengths-not-nested }
+ {
+ **** ~ Lengths ~ used ~ by ~ '#2' ~ environment ~ \msg_line_context:~\c_space_tl ****\\
+ \__enumext_show_length:nnn { dim } { labelsep } {#1}
+ \__enumext_show_length:nnn { dim } { labelwidth } {#1}
+ \__enumext_show_length:nnn { dim } { itemindent } {#1}
+ \__enumext_show_length:nnn { dim } { leftmargin } {#1}
+ \__enumext_show_length:nnn { dim } { rightmargin } {#1}
+ \__enumext_show_length:nnn { dim } { listparindent } {#1}
+ \__enumext_show_length:nnn { skip } { topsep } {#1}
+ \__enumext_show_length:nnn { skip } { parsep } {#1}
+ \__enumext_show_length:nnn { skip } { partopsep } {#1}
+ \__enumext_show_length:nnn { skip } { itemsep } {#1}
+ ****************************************************
+ }
+\msg_new:nnn { enumext } { key-ref-empty }
+ {
+ Key ~ 'ref' ~ need ~ a ~ value ~ in ~ '#1'~ \msg_line_context:.
+ }
+\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:.
+ }
+\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.
+ }
+\msg_new:nnn { enumext } { missing-starred }
+ {
+ Missing ~ '\c_backslash_str #1*' ~ #2.
+ }
+\msg_new:nnn { enumext } { many-starred }
+ {
+ Many ~ '\c_backslash_str #1*' ~ #2.
+ }
+\msg_new:nnn { enumext } { print-starred }
+ {
+ \c_backslash_str printkeyans*:~ The ~ sequence ~ '#1' ~ already ~ contains ~
+ #2 ~ environment ~ \msg_line_context:.
+ }
+\msg_new:nnn { enumext } { list-too-deep }
+ {
+ Too ~ deep ~ nesting ~ for ~ 'enumext' ~ \msg_line_context:.~ \\
+ The ~ maximum ~ level ~ of ~ nesting ~ is ~ 4.
+ }
+\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.
+ }
+\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__enumext_envir_name_tl' ~ and ~ is ~ being ~ ignored.
+ }
+ {
+ The ~ environment ~ '\l__enumext_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__enumext_envir_name_tl' ~ and ~ is ~ being ~ ignored.
+ }
+ {
+ The ~ environment ~ '\l__enumext_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 }
+ {
+ The ~ key ~ '#1' ~ is ~ unknown ~ by ~ environment~
+ '\l__enumext_envir_name_tl' ~ and ~ is ~ being ~ ignored.
+ }
+ {
+ The ~ environment ~ '\l__enumext_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__enumext_envir_name_tl' ~ and ~ is ~ being ~ ignored.
+ }
+ {
+ The ~ environment ~ '\l__enumext_envir_name_tl' ~ does ~ not
+ ~ have ~ a ~ key ~ called ~'#1'.\\
+ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly.
+ }
+\msg_new:nnnn { enumext } { standar-unknown-key }
+ {
+ The ~ key ~ '#1' ~ is ~ unknown ~ by ~ environment ~ '\l__enumext_envir_name_tl' \c_space_tl
+ ~ on ~ level ~ \int_use:N \l__enumext_level_int \c_space_tl and ~ is ~ being ~ ignored.
+ }
+ {
+ The ~ environment ~ '\l__enumext_envir_name_tl' ~ does ~ not
+ ~ have ~ a ~ key ~ called ~'#1' ~ on ~ level ~ \int_use:N \l__enumext_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__enumext_envir_name_tl' \c_space_tl
+ ~ on ~ level ~ \int_use:N \l__enumext_level_int \c_space_tl and ~ is ~ being ~ ignored.
+ }
+ {
+ The ~ environment ~ '\l__enumext_envir_name_tl' ~ does ~ not
+ ~ have ~ a ~ key ~ called ~'#1' ~ on ~ level ~ \int_use:N \l__enumext_level_int.\\
+ Check ~ that ~ you ~ have ~ spelled ~ the ~ key ~ name ~ correctly.
+ }
+\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.
+ }
+\msg_new:nnn { enumext } { undefined-storage-anskey }
+ {
+ Storage ~ named ~ '#1' ~ is ~ not ~ defined ~ \msg_line_context:.
+ }
+\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:.
+ }
+\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:.
+ }
+\msg_new:nnn { enumext } { nested }
+ {
+ The ~ environment ~ \l__enumext_envir_name_tl \c_space_tl can't ~ be ~ nested ~ \msg_line_context:.
+ }
+\msg_new:nnn { enumext } { nested-horizontal }
+ {
+ The ~ environment ~ \l__enumext_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:.
+ }
+\file_input_stop:
+%%
+%%
+%% End of file `enumext.sty'.
diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check
index db0114250c3..1a56db1cc00 100755
--- a/Master/tlpkg/bin/tlpkg-ctan-check
+++ b/Master/tlpkg/bin/tlpkg-ctan-check
@@ -306,7 +306,7 @@ my @TLP_working = qw(
enctex encxvlna endfloat endheads endiagram
endnotes endnotes-hy endnotesj endofproofwd
engpron engrec engtlc enigma enotez ensps-colorscheme
- enumitem enumitem-zref envbig enverb environ envlab eolang
+ enumext enumitem enumitem-zref envbig enverb environ envlab eolang
epcqrcode epigrafica epigram epigraph epigraph-keys epiolmec eplain
epsdice epsf epsf-dvipdfmx epsincl epslatex-fr
epspdfconversion epstopdf epstopdf-pkg
diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
index 49559201678..67e6118b0e1 100644
--- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
@@ -452,6 +452,7 @@ depend engpron
depend engrec
depend enotez
depend ensps-colorscheme
+depend enumext
depend enumitem
depend enumitem-zref
depend envbig
diff --git a/Master/tlpkg/tlpsrc/enumext.tlpsrc b/Master/tlpkg/tlpsrc/enumext.tlpsrc
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/enumext.tlpsrc