% \iffalse meta-comment % !TEX program = pdfLaTeX %<*internal> \iffalse % %<*readme> ---------------------------------------------------------------- #### oops --- An object oriented practical scribe's package, #### typically for typesetting math - Source repository: https://github.com/rogard/oops - Released under the LaTeX Project Public License v1.3c or later - See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- % %<*internal> \fi \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*install> \input docstrip.tex \keepsilent \askforoverwritefalse \preamble ---------------------------------------------------------------- oops --- An object oriented practical scribe's package, typically for typesetting math Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- \endpreamble \postamble Copyright (C) 2020 by Erwann Rogard This work may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this license or (at your option) any later version. The latest version of this license is in the file: http://www.latex-project.org/lppl.txt This work is "maintained" (as per LPPL maintenance status) by Erwann Rogard. This work consists of the file oops.dtx and the derived files oops.ins, oops.pdf and oops.sty. \endpostamble \generate{ \file{\jobname.sty}{\from{\jobname.dtx}{package}} } % % \endbatchfile %<*internal> \generate{ \file{\jobname.ins}{\from{\jobname.dtx}{install}} } \nopreamble\nopostamble \generate{ \file{README.txt}{\from{\jobname.dtx}{readme}} } \nopreamble\nopostamble \generate{ \file{README.md}{\from{\jobname.dtx}{readme}} } \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % % \RequirePackage{xparse}[2019/05/28] % \ProvidesExplPackage % {oops} % Package name % {2020/03/11} % Release date % {1.0} % Release version % {An object oriented practical scribe's package} % Description % %<*driver> \documentclass[full]{l3doc} \usepackage{oops} \usepackage{tcolorbox} \tcbuselibrary{listings,breakable} \ExplSyntaxOn \tl_gset:Nn \partname {Part} \ExplSyntaxOff \EnableCrossrefs \CodelineIndex \RecordChanges % \AtEndDocument { \PrintChanges \PrintIndex } % TODO \providecommand\pkgdata{\texttt{\meta{data}}} \providecommand\pkgoptions{\texttt{\meta{kvl0}}} \providecommand\pkgkey{\dockey{Key}} \providecommand\pkgvalue{\dockey{Value}} \providecommand\pkggenobjdefault{\texttt{Math}} \providecommand\pkgobj[1]{object identified by #1} \providecommand\pkgsep[1]{\docmarg{\texttt{#1}}} \providecommand\pkgargobj{\texttt{\meta{tl1}}} \providecommand\pkgargexpi{\texttt{\meta{tl2}}} \providecommand\pkgarginneri{\texttt{\meta{code1}}} \providecommand\pkgargsep{\texttt{\pkgsep{\meta{tl3}}\pkgsep{\meta{tl4}}\pkgsep{\meta{tl5}}}} \providecommand\pkgargouter{\texttt{\meta{code2}}} \providecommand\pkgargdefi{\texttt{\meta{kvl1}}} \providecommand\pkgarginnerii{\texttt{\meta{code3}}} \providecommand\pkgargdefii{\texttt{\meta{kvl2}}} \providecommand\pkgargexpii{\texttt{\meta{tl6}}} \providecommand\docConv[1]{Convention~\ref{#1}} \providecommand\docconv[1]{convention~\ref{#1}} \providecommand\docmarg[1]{\texttt{\char`\{#1\char`\}}} \providecommand\docopto[1]{\texttt{[}#1\texttt{]}} \providecommand\docopte[2]{#1\docmarg{#2}} \providecommand\docinlcode{\textit{inline code}} \providecommand\docInlcode{\textit{Inline code}} \providecommand\docbody{\textit{body}} \providecommand\docemptyarg{\textit{empty}} \providecommand\dockey[1]{\texttt{#1}} \providecommand\dockeyval[2]{\texttt{#1=#2}} \providecommand\docnovalue{\textit{no value}} \providecommand\docpreamb{\textit{preamble}} \providecommand\doctl{\textit{token list}} \providecommand\docTl{\textit{Token list}} \providecommand\dockvl{\textit{keyval list}} \providecommand\docKvl{\textit{Keyval list}} \providecommand\dockl{\textit{key list}} \providecommand\doclist[1]{Listing~\autoref{listing:#1}} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \GetFileInfo{\jobname.sty} % % % \title{^^A % \pkg{oops}, an object oriented practical scribe's package.\thanks{^^A % This file describes version \fileversion, last revised \filedate.^^A % }^^A % } % \author{Erwann Rogard\thanks{firstname dot lastname AusTria gmail dot com}} % % \date{Released \filedate} % % \maketitle % % \begin{abstract}\pkg{oops}~is a package for \LaTeX~(hence ``scribe'') that organizes (typically mathematical) definitions % along two dimensions: functions and objects, hence ``OO''. Such definitions are made \textit{inline} thanks to a minimalist interface built upon \pkg{xparse}\cite{xparse}. To make a definition, use \cs{OopsNew}\docmarg{\pkgargobj}, where \pkgargobj~identifies an object, followed by input that alternates between `text' and instructions. % The latter create and expand definitions using rules that can be modified at the package level or themselves inline. % This framework is suitable for instance where \pkgargobj~ is either of \texttt{ModelA} and \texttt{ModelB}, % and each requires its own definition of, say, a \textit{space}. In this case, they would be encoded respectively as \cs{Space}\docmarg{\texttt{ModelA}} and \cs{Space}\docmarg{\texttt{ModelB}}. However, this would be verbose if most functions applied to just one object, so the package provides a generic one that is set by default to \pkggenobjdefault. For example, \verb|\OopsNew{Math}[Let~]{Space=\Omega}[~denote the sample space]{}|, followed by \verb|$\Space$|, expand to: % ``\OopsNew{Math}[Let~]{Space=\Omega}[~denote the sample space]{}'' and ``$\Space$''. % Other features automate repetitive formatting tasks. Altogether, ``practical''. % \end{abstract} % % \tableofcontents % % \part{Usage}\label{part:usage} % % \addtocounter{section}{1} % \addcontentsline{toc}{section}{\protect\numberline{\thesection}Convention} % \section*{Convention}%\label{usage:conv} % % \begin{enumerate}[label=\alph*)] % \item By default, all commands are declared in the \docbody~of \cs{documentclass}. % \item Arguments expecting a \doctl\cite{tex.stack:104023}, \dockvl\cite[l3keys]{interface3}, a character, and \docinlcode, are denoted respectively % \meta{tl}, \meta{kvl}, \meta{char}, and \meta{code}. % \item \marg{arg} is either \texttt{m} or \texttt{g} options\cite{xparse}, and \docopto{\meta{arg}} and \docopte{\meta{char}}{\meta{arg}} are \texttt{o} and \texttt{e} options\cite{xparse}. % \item If we say that \meta{option} can be used to override \meta{default}, and \meta{option} is \docnovalue\cite{xparse}, we will treat it as though \meta{option}$=$\meta{default}. % \item We say ``set the key to'' as shorthand for ``set the value associated with the key to'' % \item We call \cs{code}\marg{arg}, \meta{code} with \verb|#1| replaced by \marg{arg} % \end{enumerate} % % The template for the description of functions and arguments is, where applicable: % \begin{description} % \item[Use it to] % \item[Requirement] % \item[Side effect] % \item[Expands to] % \item[Default] % \item[Example] % \item[Other] % \end{description}Only the items that cannot be deduced from other information, are given. For instance, the requirement that \pkgargobj~be a \doctl~is ommited. % % % \addtocounter{section}{1} % \addcontentsline{toc}{section}{\protect\numberline{\thesection}Loading the package} % % \begin{function}{\usepackage} % \begin{syntax} % \cs{usepackage}\docopto{\pkgoptions}\docmarg{\pkg{oops}} % \end{syntax} % \begin{description} % \item[Use it to] Load the package % \item[Requirement]\begin{enumerate} % \item \file{oops.sty} is in the path of the \LaTeX~engine. See \autoref{part:other}, \autoref{other:support}. % \item Declared in the \docpreamb~of \cs{documentclass} % \end{enumerate} % \item[Side effect] That of \cs{OopsOptions}\docmarg{\pkgoptions} % \end{description} % \end{function} % % \addtocounter{section}{1} % \addcontentsline{toc}{section}{\protect\numberline{\thesection}\cs{OopsOptions}} % \begin{function}{\OopsOptions} % \begin{syntax} % \cs{OopsOptions}\docmarg{\pkgoptions} % \end{syntax} % \begin{description} % \item[Use it to] Set default options for \cs{OopsNew} % \item[Other] Also works in the \docpreamb % \end{description} % \end{function} % % \DescribeOption{\meta{kvl}} % \begin{description} % \item[Requirement] Keys listed below. % \end{description} % % \addtocounter{subsection}{1} % \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\dockey{GenericObject}} % \DescribeOption{GenericObject} % \begin{description} % \item[Requirement] See \cs{OopsNew}, \pkgargobj % \item[Default] \verb|Math| % \end{description} % % \addtocounter{subsection}{1} % \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\dockey{Inner}} % \DescribeOption{Inner} % \begin{description} % \item[Requirement] See \cs{OopsNew}, \pkgarginneri % \item[Default] \verb|{#1}| % \end{description} % % \addtocounter{subsection}{1} % \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\dockey{Separators}} % \DescribeOption{Separators} % \begin{description} % \item[Requirement] See \cite[Section 8 of \pkg{l3seq}]{interface3} % \item[Default] \verb|{\text{~and~}{\text{,~}}{\text{,~and~}}| % \end{description} % % \addtocounter{subsection}{1} % \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\dockey{Outer}} % \DescribeOption{Outer} % \begin{description} % \item[Requirement] See \cs{OopsNew}, \pkgargouter % \item[Default] \verb|\ensuremath{#1}| % \end{description} % % \addtocounter{section}{1} % \addcontentsline{toc}{section}{\protect\numberline{\thesection}\cs{OopsClear}} % \begin{function}{\OopsClear} % \begin{syntax} % \cs{OopsClear}\docmarg{\pkgargobj} % \end{syntax} % \end{function} % % \begin{description} % \item[Side effect] Clears \pkgargobj~of any \pkgdata % \end{description} % % \addtocounter{section}{1} % \addcontentsline{toc}{section}{\protect\numberline{\thesection}\cs{OopsNew}} % \setcounter{subsection}{0} % \begin{function}{\OopsNew} % \begin{syntax} % \cs{OopsNew}\docmarg{\pkgargobj} % \docopto{\pkgargexpi} % \docopte{i}{\pkgarginneri} % \docopte{s}{\pkgargsep} % \docopte{o}{\pkgargouter} % \docmarg{\pkgargdefi} % \docopte{i}{\pkgarginnerii} % \docmarg{\pkgargdefii} % \docopto{\pkgargexpii} % \end{syntax} % \begin{description} % \item[Requirement] Only \pkgargobj~and \pkgargdefi~are mandatory % \end{description} % \end{function} % % \addtocounter{subsection}{1} % \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docmarg{\pkgargobj}} % \DescribeOption{\pkgargobj} % % \begin{description} % \item[Use it to] Identify an object % \item[Side effect] Registers \pkgargobj~ as a new object, if applicable % \item[Example] \pkggenobjdefault, \verb|ModelA|, \verb|ModelB| % \end{description} % % \addtocounter{subsection}{1} % \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docopto{\pkgargexpi}} % \DescribeOption{\pkgargexpi} % % \begin{description} % \item[Use it to] Bring about a definition % \item[Expands to] \pkgargexpi % \item[Example]\verb|Let~| % \end{description} % % \addtocounter{subsection}{1} % \phantomsection\addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docopte{i}{\pkgarginneri}} % \DescribeOption{\pkgarginneri} % % \begin{description} % \item[Use it to] Override \dockey{Inner}. % \item[Example] \verb|\mathbb{#1}| % \end{description} % % \addtocounter{subsection}{1} % \phantomsection\addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docopte{s}{\pkgargsep}} % \DescribeOption{\pkgargsep} % % \begin{description} % \item[Use it to] Override \dockey{Separators} % \item[Example] \verb|{~\&~}{,~}{~\&~}| % \end{description} % % \addtocounter{subsection}{1} % \phantomsection\addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docopte{o}{\pkgargouter}} % \DescribeOption{\pkgargouter} % % \begin{description} % \item[Use it to] Override \dockey{Outer} % \item[Example] \verb|\text{#1}| % \end{description} % % \addtocounter{subsection}{1} % \phantomsection\addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docmarg{\pkgargdefi}} % \DescribeOption{\pkgargdefi} % % \begin{description} % \item[Side effect] If \pkgkey~is a new key, attaches to it \pkgdata=\cs{\pkgarginneri}\docmarg{\pkgvalue} % \item[Expands to] If \pkgargexpi~is \docnovalue, none, otherwise, % \begin{enumerate} % \item % For each \pkgkey, calls \cs{\pkgkey}\pkgargobj. Call it \meta{seq}. % \item % Concatenates \meta{seq} using \pkgargsep. Call it \meta{tmp}. % \item Expands \cs{\pkgargouter}\marg{tmp} % \end{enumerate} % \item[Example] \verb|Sample=\Omega| % \end{description} % % The remaining options taken together forward to: % % \cs{OopsNew}\docmarg{\pkgargobj} % \docopte{o}{\pkgarginnerii} % \docmarg{\pkgargdefii} % \docopto{\pkgargexpii} % % \addtocounter{subsection}{1} % \phantomsection\addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docopte{i}{\pkgarginnerii}} % \DescribeOption{\pkgarginnerii} % % \addtocounter{subsection}{1} % \phantomsection\addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docmarg{\pkgargdefii}} % \DescribeOption{\pkgargdefii} % % \addtocounter{subsection}{1} % \addcontentsline{toc}{subsection}{\protect\numberline{\thesubsection}\docopto{\pkgargexpii}} % \DescribeOption{\pkgargexpii} % % \addtocounter{section}{1} % \addcontentsline{toc}{section}{\protect\numberline{\thesection}\cs{\meta{Key}}} % \setcounter{subsection}{0} % % \begin{function}{\} % \begin{syntax} % \cs{\meta{Key}}\docopto{\pkgargobj} % \end{syntax} % \begin{description} % \item[Side effect] Expands to \pkgdata~associated with \pkgargobj~and \dockey{\meta{Key}}, if applicable. % \end{description} % \end{function} % % \clearpage % \part{Listings}\label{part:listing} % % \newtcblisting[auto counter] % {listing}[2][]{ % noparskip, % breakable, % colback=white, % colframe=black, % opacitybacktitle=.8,% % fonttitle=\bfseries, % title=Listing~\thetcbcounter. #1, % arc=0pt, % outer arc=0pt, % boxrule=1pt, % #2 % } % % \phantomsection\addcontentsline{toc}{section}{\doclist{options:i}.} % \begin{listing}[] % {label=listing:options:i} % \OopsOptions % { % Inner = {#1}, % Outer = {#1} % } % \end{listing} % % \phantomsection\addcontentsline{toc}{section}{\doclist{foo:i}.} % \begin{listing}[]{label=listing:foo:i} % \OopsNew{Foo}{ Barr = { a }, Baz = { b } }{ Qux = { c } } % \textless(\Barr[Foo]), (\Baz[Foo]) \& (\Qux[Foo])\textgreater % \end{listing} % % \phantomsection\addcontentsline{toc}{section}{\doclist{foo:ii}.} % \begin{listing}[]{label=listing:foo:ii} % \OopsNew{Foo}[]i{(#1)}s{{~\&~}{,~}{~\&~}}o{\textless#1\textgreater}{ Barr = { a }, Baz = { b }, Qux = { c } } % \end{listing} % % \phantomsection\addcontentsline{toc}{section}{\doclist{foo:iii}.} % \begin{listing}[]{label=listing:foo:iii} % \OopsOptions % { % Inner = {(#1)}, % Separators = { {~\&~}{~,~}{~\&~} }, % Outer = {\textless#1\textgreater} % } % \OopsNew{Foo}[]{ Barr = { a }, Baz = { b }, Qux = { c } } % \end{listing} % % \phantomsection\addcontentsline{toc}{section}{\doclist{foo:iv}.} % \begin{listing}[] % {label=listing:foo:iv} % \OopsOptions % { % Inner, % Separators, % Outer % } % \end{listing} % % \phantomsection\addcontentsline{toc}{section}{\doclist{math:i}.} % \begin{listing}[] % {label=listing:math:i} % \OopsNew{Math}[We call~]{Elems={\omega_1, \dots, \omega_n}} % [~the elementary events, and ]{}{Space=\Omega} % [\begin{equation*}\Space=(\Elems)\end{equation*}~the sample space.] % {} % \end{listing} % % % \phantomsection\addcontentsline{toc}{section}{Listing~\autoref{listing:math:ii}.} % \begin{listing}[] % {label=listing:math:ii} % \OopsClear{Math} % \OopsNew{Math}[Let ]s{{,}{,}{,}}o{\ensuremath{\{#1\}}} % {Space=\Omega, SigmaField=\mathcal{F}, Measure=\mathcal{P}} % [~denote the probability space, where $\SigmaField\subset 2^{\Space}$.] % {} % \end{listing} % \phantomsection\addcontentsline{toc}{section}{Listing~\autoref{listing:mvt}.} % \begin{listing}[]{label=listing:mvt} % \newtheorem{theorem}{Theorem} % \OopsNew{Math} % i{\mathbb{#1}}{ N = { N } , R = { R } } % [\begin{theorem}[Mittelwertsatz f\"ur $n$ Variable]Es sei~] % {} % { % OffeneMenge={D}, % Ci={C^{1}}, % Strecke={[x_0,x]} %^^A %Strecke={\char`[x_0,x\char`]} % Also works %^^A %Strecke={\[x_0,x\]} % BUG % } % [$n\in\N$, $\OffeneMenge\subseteq\N^n$ eine offene Menge und $f\in \Ci(\OffeneMenge,\R)$. % Dann gibt es auf jeder Strecke $\Strecke\subset\OffeneMenge$ einen Punkt $\xi\in\Strecke$, ] % {} % { % yDifferenz={f(x)-f(x_0)}, % xDifferenz={x-x_0}, % Steigung={\frac{\yDifferenz}{\xDifferenz}} % } % [so dass gilt \begin{equation*}\Steigung = \operatorname{grad} f(\xi)^{\top}\end{equation*} % \end{theorem}] % {} % \end{listing} % % \StopEventually{^^A % \PrintChanges % \PrintIndex % } % \part{Other}\label{part:other} % \section{Acknowledgment} % % This work has benefited from Q\&A's from the \LaTeX community. For specifics, see here: \url{https://tex.stackexchange.com/users/112708/erwann?tab=questions} % \doclist{math:i} and \doclist{math:ii} are from \cite{shir95}. \doclist{mvt} is from \pkg{tcolbox}\cite[17.3]{tcolbox}. % % \begin{thebibliography}{1} % \bibitem{shir95} A.N. Shiryaev {\em Probability} Springer, 1995 % \bibitem{interface3} The \LaTeX3 Project Team {\em The \LaTeX3 interfaces} % \url{http://ftp.math.purdue.edu/mirrors/ctan.org/macros/latex/contrib/l3kernel/interface3.pdf} % \bibitem{xparse} The \LaTeX3 Project Team {\em The \pkg{xparse} package} % \url{http://ftp.math.purdue.edu/mirrors/ctan.org/macros/latex/contrib/l3packages/xparse.pdf} % \bibitem{tcolbox} Thomas F. Sturm {\em The \pkg{tcolorbox} package} % \url{http://www.texdoc.net/texmf-dist/doc/latex/tcolorbox/tcolorbox.pdf} % \bibitem{tex.stack:104023} \url{https://tex.stackexchange.com/questions/104023/what-is-a-token#104025} % \end{thebibliography} % % \section{Bug}\label{other:bug} % % See \doclist{math:ii}. Low priority as there are workarounds. % % \section{Disclaimer}\label{other:discl} % % This package has not been tested beyond \autoref{part:listing}. % % Option type \texttt{G} is supported but not recommended by \pkg{xparse}\cite{xparse}, but it's really practical in this case. % \section{Support}\label{other:support} % % This package is available from \url{https://www.ctan.org/pkg/oops} (release) or \url{https://github.com/rogard/oops} (development) where you can report issues. % % \section{To do}\label{other:todo} % % \begin{enumerate} % \item Continue \autoref{part:listing} based on \cite[Section 17.3]{tcolbox} % \end{enumerate} % %^^A \section{Changes} % % \changes{v1.0}{2019/03/08}{Initial version} % % \clearpage % \part{Implementation}\label{part:impl} % % \iffalse %<*package> % \fi % \section{Back end} % \subsection{Aux} % \subsubsection{Msg} % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}[2019/10/01] \ExplSyntaxOn \msg_new:nnn {Oops} {generic} {#1} % \end{macrocode} % \subsubsection{Variables} % \begin{macrocode} \seq_new:N \__erw_oops_seq % \end{macrocode} % \subsubsection{Options} % \begin{macrocode} \keys_define:nn { Oops } { GenericObject .tl_gset:N = \__erw_oops_object_default_tl, GenericObject .value_required:n = false, GenericObject .default:n = {Math}, GenericObject .initial:n = {Math}, Inner .code:n = { \cs_gset:Npn \__erw_oops_inner_default:n ##1{#1} }, Inner .value_required:n = false, Inner .default:n = {#1}, Inner .initial:n = {#1}, Separators .tl_gset:N = \__erw_oops_separators_default_tl, Separators .value_required:n = false, Separators .default:n = {{ \text{~and~}}{\text{,~}}{\text{,~and~}}}, Separators .initial:n = {{ \text{~and~}}{\text{,~}}{\text{,~and~}}}, Outer .code:n = { \cs_gset:Npn \__erw_oops_outer_default:n ##1{#1} }, Outer .value_required:n = false, Outer .default:n = {\ensuremath{#1}}, Outer .initial:n = {\ensuremath{#1}} } % \end{macrocode} % \subsection{Prop} % \subsubsection{name} % \begin{macrocode} \cs_new:Npn \__erw_oops_name:n #1{__erw_oops_#1} % \end{macrocode} % \subsubsection{new} % \begin{macrocode} \cs_new_protected:Nn \__erw_oops_new:n { \prop_new:c{\__erw_oops_name:n { #1 }} } \cs_new_protected:Nn \__erw_oops_clear_new:n { \prop_clear_new:c{\__erw_oops_name:n { #1 }} } % \end{macrocode} % \subsubsection{put} % \begin{macrocode} \cs_new_protected:Nn \__erw_oops_put:nnn { \prop_put:cnn { \__erw_oops_name:n { #1 } } { #2 } { #3 } } \cs_new_protected:Nn \__erw_oops_putinner:nnn { \__erw_oops_put:nnn{#1} {#2} {\__erw_oops_inner:n{#3}} } % \end{macrocode} % \subsubsection{item} % \begin{macrocode} \cs_new:Nn \__erw_oops_item:nn { \prop_item:cn { \__erw_oops_name:n { #1 } } { #2 } } \cs_new:Npn \__erw_oops_item:nnn #1 #2 #3 { \__erw_oops_item:nn{#1}{#2} } \cs_new:Nn \__erw_oops_itemcmd:Nn { \ProvideDocumentCommand{#1} {O{\__erw_oops_object_default_tl}} { \__erw_oops_item:nn {##1}{ #2 } } } \cs_generate_variant:Nn \__erw_oops_itemcmd:Nn {c} \cs_new:Npn \__erw_oops_itemcmd:nnn #1 #2 #3 { \__erw_oops_itemcmd:cn{#2}{#2} } \cs_new:Npn \__erw_oops_itemto_seq:nnn #1 #2 #3 { \seq_put_right:Nn \__erw_oops_seq {\__erw_oops_item:nn{#1}{#2}} } % \end{macrocode} % \subsubsection{conditional} % \begin{macrocode} \cs_new:Nn \__erw_oops_if_exist:nTF { \prop_if_exist:cTF{\__erw_oops_name:n { #1 }}{#2}{#3} } % \end{macrocode} % \subsubsection{parse} % \begin{macrocode} \cs_set:Npn \__erw_oops_parse:Nnn #1 % fun #2 % prop name #3 % clist { \tl_if_blank:nTF{#3} {\c_empty_tl} { \seq_set_split:Nnn \l_tmpa_seq {,}{#3} \cs_set:Npn \__erw_oops_parse:w ##1 = ##2 \q_stop { #1 {#2} {\tl_trim_spaces:n{##1}} % key {\tl_trim_spaces:n{##2}} % value } \cs_set:Npn \__erw_oops_parse:n ##1 { \__erw_oops_parse:w ##1 \q_stop } \seq_map_function:NN \l_tmpa_seq \__erw_oops_parse:n } } % \end{macrocode} % \section{Front end} % \subsection{\cs{OopsOptions}} % \begin{macrocode} \NewDocumentCommand{\OopsOptions} {m} { \keys_set:nn { Oops } {#1} } % \ProcessKeysPackageOptions{ Oops } % \end{macrocode} % \subsection{\cs{OopsClear}} % \begin{macrocode} \NewDocumentCommand{\OopsClear} {m} { \__erw_oops_clear_new:n{#1} } % \end{macrocode} % \subsection{\cs{OopsNew}} % \begin{macrocode} \NewDocumentCommand{\OopsNew} { m +o E{iso} { {\__erw_oops_inner_default:n{##1}} {\__erw_oops_separators_default_tl} {\__erw_oops_outer_default:n{##1}} } m E{i} { {\__erw_oops_inner_default:n{##1}} } g +o } { \__erw_oops_if_exist:nTF{#1} {\c_empty_tl} {\__erw_oops_new:n{#1}} \IfValueTF{#2} {#2} {\c_empty_tl} \cs_gset:Npn \__erw_oops_inner:n ##1 {#3} \__erw_oops_parse:Nnn \__erw_oops_putinner:nnn {#1} {#6} \__erw_oops_parse:Nnn \__erw_oops_itemcmd:nnn {#1} {#6} \IfValueTF{#2} { \seq_clear:N \__erw_oops_seq \__erw_oops_parse:Nnn \__erw_oops_itemto_seq:nnn {#1} {#6} \cs_gset:Npn \__erw_oops_outer:n ##1 {#5} \__erw_oops_outer:n {\exp_last_unbraced:NNo \seq_use:Nnnn \__erw_oops_seq {#4} } } {\c_empty_tl} \IfValueTF{#8} { \IfValueTF{#9} { \exp_not:n{\OopsNew{#1}i{#7}{#8}[#9]} } { \exp_not:n{\OopsNew{#1}i{#7}{#8}} } } { \IfValueTF{#9} { \exp_not:n{\OopsNew{#1}[#9]} } {\c_empty_tl} } } % \end{macrocode} % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % \iffalse % % \fi % \Finale \endinput