diff options
author | Karl Berry <karl@freefriends.org> | 2024-11-01 21:26:09 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2024-11-01 21:26:09 +0000 |
commit | b52be2f59db36993de24df6c7e61d2ce674d528a (patch) | |
tree | 08f80abba884a45632000224c0ce449165b3b63a | |
parent | 470dbc5d151043007149361d8e04ec509c9f5faf (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.md | 69 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enumext/enumext.pdf | bin | 0 -> 1643633 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/enumext/enumext.dtx | 15804 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/enumext/enumext.ins | 53 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/enumext/enumext.sty | 6115 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 2 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/enumext.tlpsrc | 0 |
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>⟨multicol⟩</code> and <code>⟨scontents⟩</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>⟨enumext⟩</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>⟨enumext.pdf⟩</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>⟨enumext⟩</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 + +- ⟨`README.md`⟩ \(this file\) +- ⟨`enumext.pdf`⟩ \(documentation\) +- ⟨`enumext.dtx`⟩ \(master file that produced all files\) +- ⟨`enumext.ins`⟩ \(installer to extract all files\) + +## Author and copyright + +Copyright © 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 Binary files differnew file mode 100644 index 00000000000..0a70a539d52 --- /dev/null +++ b/Master/texmf-dist/doc/latex/enumext/enumext.pdf 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 |