From 8c69df7f8b72005b3d333b30388fb69d20ebb22a Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 18 Mar 2019 21:16:17 +0000 Subject: exercisebank (18mar19) git-svn-id: svn://tug.org/texlive/trunk@50448 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/latex/exercisebank/exercisebank.sty | 958 +++++++++++++-------- 1 file changed, 597 insertions(+), 361 deletions(-) (limited to 'Master/texmf-dist/tex/latex/exercisebank') diff --git a/Master/texmf-dist/tex/latex/exercisebank/exercisebank.sty b/Master/texmf-dist/tex/latex/exercisebank/exercisebank.sty index 60cf10076d5..9e13d79ea7e 100644 --- a/Master/texmf-dist/tex/latex/exercisebank/exercisebank.sty +++ b/Master/texmf-dist/tex/latex/exercisebank/exercisebank.sty @@ -1,5 +1,5 @@ % Source (with comments) can be found at https://github.com/Strauman/exercisebank/ -%% The LaTeX package exercisebank - version v0.2.2 (2018/10/04) - build 97 +%% The LaTeX package exercisebank - version v0.3.0 (2019/03/18) - build 137 %% exercisebank.sty: Exercise bank %% ------------------------------------------------------------------------------------------- %% Copyright (c) 2018 by Andreas Storvik Strauman @@ -13,17 +13,78 @@ %% version 2008/05/04 or later. %% This work has the LPPL maintenance status `author-maintained'. %% This work consists of all files listed in README -\ProvidesPackage{exercisebank}[2018/10/04 v0.2.2 Creates a setup that gives freedom in making sets and exercises.] +\ProvidesPackage{exercisebank}[2019/03/18 v0.3.0 Creates a setup that gives freedom in making sets and exercises.] \xdef\exbank@quiet{1} -\def\exercisebankversion{v0.2.2 - Build 97} -\PackageWarningNoLine{exercisebank-v0.2.2}{This package is in the beta stage, and if something unexpected happens please, oh pretty please, report it to https://github.com/Strauman/exercisebank. Thank you!} +\def\exercisebankversion{v0.3.0 - Build 137} +\PackageWarningNoLine{exercisebank-v0.3.0}{This package is in the beta stage, and if something unexpected happens please, oh pretty please, report it to https://github.com/Strauman/exercisebank. Thank you!} \@ifundefined{ownLineNoSpacesGotIt}{\@latex@warning{Compilation wont work unless \string\end{problem} and \string\end{solution} are on their own lines and without any spaces. This warning can be removed by doing \string\def\string\ownLineNoSpacesGotIt{} before \@backslashchar usepackage{exercisebank}} }{} +\ifcsname pdfstrcmp\endcsname\else +\PackageError{exercisebank-v0.3.0}{Exercisebank currently only works with pdfLaTeX}{}\stop +\fi \gdef\setExercisesDir#1{\@latex@error{\string\setExercisesDir is deprecated. Use \string\exercisebanksetup{exercise directory=#1} instead}{}\stop\bye } \@ifundefined{exercisesDir}{\gdef\@exercisesDir{.} }{} \global\let\incl = \input +\def\exb@rememberCC#1{% + \edef\exbtmp@charcode{\the\numexpr#1}% + \expandafter\xdef\csname exb@remcc@\exbtmp@charcode\endcsname{\the\catcode#1}% +} +\def\exb@ignoreCC#1{% + \edef\exbtmp@charcode{\the\numexpr#1} + \exb@rememberCC{\exbtmp@charcode}% + \catcode\exbtmp@charcode=9% +} +\def\exb@resetCC#1{ \catcode#1=\csname exb@remcc@\the\numexpr#1\endcsname +} +\def\ignoreOutlineSpaces{% + \exb@ignoreCC{10}% + \exb@ignoreCC{11}% + \exb@ignoreCC{12}% + \exb@ignoreCC{13}% +} +\def\obeyOutlineSpaces{% + \exb@resetCC{10}% + \exb@resetCC{11}% + \exb@resetCC{12}% + \exb@resetCC{13}\ignorespaces% +} +\let\ignoreOutlineSpaces\relax +\let\obeyOutlineSpaces\relax +\def\g@newif#1{% + \count@\escapechar\escapechar\m@ne + \global\let#1\iffalse% + \g@if#1\iftrue% + \g@if#1\iffalse% +\escapechar\count@} +\def\g@if#1#2{% + \expandafter\def\csname\expandafter\@gobbletwo\string#1% + \expandafter\@gobbletwo\string#2\endcsname% + {\global\let#1#2}% +} +\global\newif\ifexbset@nextprob@header +\global\exbset@nextprob@headertrue +\newif\ifexb@opthides +\g@newif\ifexb@b@nextprob@header +\g@newif\ifexb@solutionsonly +\g@newif\ifexb@isFirstProblem +\g@newif\ifexb@opt@tightenparagraphs +\g@newif\ifexb@DisplaySolutions +\g@newif\ifexb@DisplayCurrentSolution +\g@newif\ifexb@DisplayCurrentProblem +\g@newif\ifexbank@if@needspace +\g@newif\ifexb@opt@partProblems +\g@newif\ifexb@opt@doMargins +\g@newif\ifexb@CountIntros +\g@newif\ifexb@noheadArg +\g@newif\ifexb@showtags +\g@newif\ifexb@showCurrent@PPHeader +\g@newif\ifexb@showLonelyPartProblems +\global\exb@showLonelyPartProblemsfalse +\global\exb@showCurrent@PPHeadertrue +\exb@b@nextprob@headerfalse +\exbank@if@needspacetrue \usepackage{xstring} \usepackage{pgffor} \usepackage{scrextend} @@ -60,7 +121,7 @@ \fi% }% \fi} -\gdef\exb@warn{\PackageWarningNoLine{exercisebank-v0.2.2}} +\gdef\exb@warn{\PackageWarningNoLine{exercisebank-v0.3.0}} \gdef\exb@err#1{\PackageError{exercisebank}{#1}{}} \newif\ifexb@isInList \newcounter{exb@isin@dots} @@ -138,38 +199,39 @@ \global\catcode`\^^J=12\relax% \global\catcode`\ =10\relax% } -\let\nextPar\everypar +\def\@AtNextParHook{} +\let\oldep\everypar +\oldep{\the\everypar} \newtoks\everypar -\nextPar{\the\everypar} -\def\AtNextPar#1{\nextPar\expandafter{\the\nextPar\nextPar{\the\everypar}#1}} +\oldep{\the\everypar\@AtNextParHook\relax\gdef\@AtNextParHook{}} +\def\AtNextPar#1{\g@addto@macro\@AtNextParHook{#1}} +\gdef\exercisebankversion{\PackageWarningNoLine{exercisebank}{Version v0.3.0b137}} +\gdef\exercisebankbuild{\PackageWarningNoLine{exercisebank}{Build 137}} \edef\@isTrue{1} \edef\@isFalse{0} \gdef\ShowNumbers{\gdef\@displayMetaCounter{\isTrue}} -\gdef\exb@showtags{\isFalse} -\gdef\ShowTags{\gdef\exb@showtags{\isTrue}} +\global\exb@showtagsfalse +\gdef\ShowTags{\global\exb@showtagstrue} \gdef\exb@printCurrentTags{Tags: \exb@currentTags~} -\gdef\ShowFilenames{\At\VeryBeginProblem{\exerciseFile\\}} -\gdef\@DisplaySolutions{\@isFalse} -\gdef\DisplaySolutions{\xdef\@DisplaySolutions{\isTrue}\@latex@warning{Showing solutions}} -\gdef\ifDisplaySolutions{\if\@DisplaySolutions\@isTrue} -\gdef\@SolutionsOnly{\@isFalse} -\gdef\SolutionsOnly{\xdef\@SolutionsOnly{\@isTrue}\DisplaySolutions} +\gdef\ShowFilenames{\At\InputExerciseFile{File: {\ttfamily \@exercisesDir/\exerciseFile}\par}} +\global\exb@DisplaySolutionsfalse +\gdef\DisplaySolutions{\global\exb@DisplaySolutionstrue\@latex@warning{Showing solutions}} +\gdef\SolutionsOnly{\DisplaySolutions\global\exb@solutionsonlytrue} \gdef\exb@currentPoints{0} -\newif\ifexbank@if@needspace -\global\exbank@if@needspacetrue \pgfkeys{/exbanksetup/.is family, /exbanksetup, -default/.style = { part problems = On, - tighten paragraphs = True, - problem header={\normalsize\Large\bfseries\@tr{Problem}~\theproblemcounter}, +default/.style = { part problems = true, + tighten paragraphs = true, + problem header={\Large\bfseries\@tr{Problem}~\theproblemcounter}, part problem header={\large\textbf{(\theproblemcounter\alph{partproblemcounter})}}, part problem header suffix={}, solution header={\large{\textbf{\@tr{Solution}:}}}, exercise directory=., figure root directory=\@exercisesDir, - style margins=On, + style margins=true, problem needs space=0.2\paperheight, - no needspace/.is if={exbank@if@needspace}, - no needspace/.default = false + needspace/.is if={exbank@if@needspace}, + no needspace/.code = {\global\ifexbank@if@needspacefalse}, + show lonely part problems/.is if={exb@showLonelyPartProblems} }, exercise directory/.estore in = \@exercisesDir, % figure root directory/.estore in = \@figrootDir, % @@ -180,9 +242,9 @@ part problem header/.store in = \exbank@opt@partProblemHeader, solution header/.store in = \exbank@opt@solutionHeader, problem needs space/.store in = \exbank@opt@problemneedspace, part problem header suffix/.store in=\exb@partproblem@header@suffix, -part problems/.style = {switches/#1/.get = \exbank@opt@partProblems}, -tighten paragraphs/.style = {switches/#1/.get = \exbank@opt@tightenparagraphs}, -style margins/.style={switches/#1/.get = \exbank@opt@doMargins}, +part problems/.is if = {exb@opt@partProblems}, +tighten paragraphs/.is if = {exb@opt@tightenparagraphs}, +style margins/.is if ={exb@opt@doMargins}, switches/.cd, On/.initial = \@isTrue, on/.initial = \@isTrue, @@ -198,24 +260,59 @@ switches/.cd, \exercisebanksetup{default} \AtBeginDocument{\xdef\tpd{\the\prevdepth}} \gdef\tighten@paragraph{% -\if\exbank@opt@tightenparagraphs\@isTrue\relax% - \filbreak% +\ifexb@opt@tightenparagraphs\relax% + \filbreak% \fi% } \gdef\tighten@paragraph@solutions{% -\if\exbank@opt@tightenparagraphs\@isTrue\relax% - \if\@SolutionsOnly\@isFalse - \if\@DisplaySolutions\@isTrue - \filbreak% - \fi +\ifexb@opt@tightenparagraphs% + \ifexb@DisplaySolutions% + \filbreak% \fi \fi% } \gdef\tighten@paragraph@always{% -\if\exbank@opt@tightenparagraphs\@isTrue\relax% +\ifexb@opt@tightenparagraphs% \filbreak% \fi% } +\@dlog{unfilbreak@exercisebank} +\@ifdefinable\@My@filbreak@counter{\newcount\@My@filbreak@counter} +\global \@My@filbreak@counter = 0 +\@ifdefinable\@My@filbreak@mark{\newmarks\@My@filbreak@mark} +\renewcommand*\filbreak{% + \par + \global\advance \@My@filbreak@counter \@ne + \marks\@My@filbreak@mark{\number\@My@filbreak@counter}% + \vfil + \penalty -200 + \vfilneg +} +\newcommand*\@My@finish@stopfilbreak{} +\newcommand*\stopfilbreak{% + \par + \ifnum\prevdepth >\@m \else\prevdepth \z@ \fi + \nobreak\null + \nobreak\vskip -\baselineskip + \penalty\z@ + \begingroup + \output{% + \typeout{t: \the\pagetotal, g: \the\pagegoal}% + \unvbox\@cclv + \ifnum 0\topmarks\@My@filbreak@mark <\@My@filbreak@counter + \gdef\@My@finish@stopfilbreak{% + \penalty\z@% +}% + \else + \gdef\@My@finish@stopfilbreak{% + \penalty\z@ % +}% + \fi +}% + \break + \endgroup + \@My@finish@stopfilbreak +} \pgfkeys{ /exbanki18n/.is family, /exbanki18n, default/.style = {Problem = Problem, Solution = Solution}, Problem/.estore in = \@tr@Problem, @@ -229,42 +326,63 @@ switches/.cd, \csname @tr@#1\endcsname% }% } +\newif\ifat@isrigid \let\ea = \expandafter \begingroup\lccode`\|=`\\ \lowercase{\endgroup\def\removebs#1{\if#1|\else#1\fi}} \ifcsname at@verbose\endcsname -\global\def\@triggerLog#1{\@latex@warning{--\string\TRIGGER: #1}}% + \global\def\@triggerLog#1{\@latex@warning{--\string\TRIGGER: #1}}% \else -\global\let\@triggerLog\@gobble% + \global\let\@triggerLog\@gobble% \fi -\newcommand{\At}[2]{ \edef\mname{\exbank@macroname{#1}}% - \ifcsname At@\mname\endcsname% - \ea\g@addto@macro\csname At@\mname\endcsname{#2}% - \else% - \ea\gdef\csname At@\mname\endcsname{#2}% - \AtEndDocument{% - \expandafter\let\csname At@\mname\endcsname\relax% -} - \fi% +\newcommand{\At}[2]{% + \edef\mname{\exbank@macroname{#1}}% + \ifcsname At@\mname\endcsname% + \ea\g@addto@macro\csname At@\mname\endcsname{#2}% + \else% + \ifat@isrigid + \ea\gdef\csname Rigid@At@\mname\endcsname{#2}% + \else + \ea\gdef\csname At@\mname\endcsname{#2}% + \fi% + \fi% + \global\at@isrigidfalse% } +\let\@rigid\at@isrigidtrue \newcommand{\Trigger}[1]{% - \edef\mname{\exbank@macroname{#1}}% - \ea\@ifundefined{At@\mname}{}{% - \@triggerLog{\mname}\csname At@\mname\endcsname% + \edef\mname{\exbank@macroname{#1}}% + \ea\@ifundefined{Rigid@At@\mname}{}{% + \@triggerLog{\mname}\csname Rigid@At@\mname\endcsname% +}% + \ea\@ifundefined{At@\mname}{}{% + \@triggerLog{\mname}\csname At@\mname\endcsname% }% } +\newcommand{\exb@ClearHook}[1]{% + \edef\mname{\exbank@macroname{#1}}% + \expandafter\let\csname At@\mname\endcsname\relax% + \ifat@isrigid + \expandafter\let\csname Rigid@At@\mname\endcsname\relax% + \fi + \global\at@isrigidfalse% +} \xdef\figuresPath{\@figrootDir/} \gdef\fileInputPath{} +\gdef\thisfilepath{} % \gdef\fileInputBase{} +\@ifundefined{input@path}{\gdef\input@path{}}{} +\AtBeginDocument{% \providecommand*{\input@path}{} -\g@addto@macro\input@path{{\fileInputBase}{\fileInputPath}} +\providecommand*{\Ginput@path}{} +\g@addto@macro\input@path{{\fileInputBase}{\fileInputPath}}% +\g@addto@macro\Ginput@path{{\fileInputBase}{\fileInputPath}}% +} \At\PathControl{ \xdef\figuresPath{\@figrootDir/} \edef\exfile{\exerciseFile} \expandafter\filename@parse{\exfile} + \xdef\thisfilepath{\@exercisesDir/\filename@area} \xdef\fileInputPath{\figuresPath\filename@area} \xdef\fileInputBase{\figuresPath\filename@area\filename@base/} - \graphicspath{{\fileInputBase}{\fileInputPath}} - \@ifundefined{input@path}{\gdef\input@path{{\fileInputBase}{\fileInputPath}}}{} } \newlength{\pMarginBelow} \newlength{\pMarginAbove} @@ -272,43 +390,36 @@ switches/.cd, \newlength{\ppMarginBelow} \newlength{\ppMarginAbove} \newlength{\ppMargin} -\newlength{\introMargin} -\newlength{\solutionMarginLeft} +\newlength{\introOutdent} \newlength{\solutionMarginAbove} -\edef\defaultLeftMargin{\the\dimexpr1in+\hoffset} -\setlength{\ppMargin}{0.5em} +\setlength\parindent{0pt} \setlength{\pMarginLeft}{-\ppMargin-2.5em} -\setlength{\solutionMarginLeft}{\ppMargin} +\setlength{\pMarginBelow}{1.5em \@plus .5em \@minus .5em} +\setlength{\pMarginAbove}{0pt} +\setlength{\ppMargin}{0.5em} +\setlength{\ppMarginBelow}{0em} +\setlength{\ppMarginAbove}{0.5\baselineskip} +\setlength{\introOutdent}{1em} \setlength{\solutionMarginAbove}{1em} -\setlength{\pMarginBelow}{0em} -\setlength{\pMarginAbove}{\baselineskip} -\setlength{\introMargin}{-1.5em} -\setlength{\ppMarginBelow}{\baselineskip} -\setlength{\ppMarginAbove}{0em} -\setlength\parindent{0pt} -\newbox\ppmarkbox -\newlength\markskip -\setlength\markskip{4\baselineskip} -\def\solMargin{\dimexpr\ppMargin\relax} -\def\vsSize{1em} -\def\vs{\vspace{\vsSize}} \newcounter{problemcounter} \setcounter{problemcounter}{0} \newcounter{partproblemcounter} \At\VeryBeginProblem{% - \if\exbank@opt@tightenparagraphs\@isTrue\relax% + \ifexb@opt@tightenparagraphs% \ifexbank@if@needspace\needspace{\exbank@opt@problemneedspace}\fi% - \vskip-2\baselineskip\relax% \fi% \stepcounter{problemcounter}% \setcounter{partproblemcounter}{0}% - \vspace*{\pMarginAbove}% - \strut\vadjust{\vbox to 0pt{\if\exbank@opt@doMargins\@isTrue\hskip\pMarginLeft\fi{\exbank@opt@problemHeader}\vss}}\par% - \vspace*{\the\dimexpr\baselineskip+\pMarginBelow}% + \vspace\pMarginAbove% + \strut\vadjust{\vbox to 0pt{\ifexb@opt@doMargins\relax\hskip\pMarginLeft\fi{\exbank@opt@problemHeader}\vss}}\par% + \vspace\pMarginBelow\relax% } \At\EndProblem{% \tighten@paragraph% }% +\At\BeginPartproblem{% +\vspace\ppMarginAbove\relax% +} \At\VeryBeginPartproblem{% \@dinfo{Triggered Beginning Part Problem (\string\VeryBeginPartproblem)}% \stepcounter{partproblemcounter}% @@ -318,152 +429,201 @@ switches/.cd, \if\@displayMetaCounter\@isTrue\relax% \gdef\exb@prePPHead{{\Large\themetacounter}:}% \fi% - \if\exb@showtags\isTrue% - \gdef\exb@postPPHead{\exb@printCurrentTags}% + \ifexb@showtags% + \g@addto@macro\exb@postPPHead{\exb@printCurrentTags}% \fi% -\ifnum\pdfstrcmp{\exbank@opt@doMargins}{\@isTrue}=\z@\relax% -\newbox\nobox% -\gdef\exb@pp@lefttag{\leavevmode{\smash{\llap{{\exb@prePPHead\exbank@opt@partProblemHeader\Trigger\PartProblemHeaderSuffix}\hskip\ppMargin}\exb@postPPHead}}}% +\ifexb@opt@doMargins% +\let\exb@partProblemHeader\exbank@opt@partProblemHeader% +\ifexb@b@nextprob@header\relax% + \global\exb@b@nextprob@headerfalse% + \addtocounter{partproblemcounter}{-1}% + \let\exb@partProblemHeader\exb@nextprob@header% +\fi% +\gdef\exb@pp@lefttag{\leavevmode{\smash{\llap{{\exb@prePPHead\exb@partProblemHeader\Trigger\PartProblemHeaderSuffix}\hskip\ppMargin}\exb@postPPHead}}}% \else% -\gdef\exb@pp@lefttag{{\exbank@opt@partProblemHeader\Trigger\PartProblemHeaderSuffix}}% +\gdef\exb@pp@lefttag{{\exb@partProblemHeader\Trigger\PartProblemHeaderSuffix}}% \fi% -\AtNextPar{\exb@pp@lefttag}% -\ignorespaces}% +\ifexb@showCurrent@PPHeader% +\AtNextPar{\exb@pp@lefttag\global\let\exb@pp@lefttag\relax\Trigger\AfterPPHeader}\par% +\else% +\par% +\fi\ignorespaces}% \At\EndPartproblem{% - \vspace*{\pMarginBelow}% - \tighten@paragraph\par% + \vspace\ppMarginBelow\relax% + \tighten@paragraph% + \global\exb@showCurrent@PPHeadertrue } -\At\BeginSolution{\hfill\break\vspace*{\solutionMarginAbove}{\exbank@opt@solutionHeader}} +\At\BeginSolution{\ifexb@solutionsonly\else\hfill\break\vspace{\solutionMarginAbove}\fi{\exbank@opt@solutionHeader}} \At\EndSolution{} -\newif\ifexb@opthides +\newcounter{numppInFile} +\At\BeginPartproblem{% + \ifcsname exb@numexercises@\the\numexpr\the\c@problemcounter\endcsname% + \edef\numppex{\csname exb@numexercises@\the\numexpr\the\c@problemcounter\endcsname}% + \ifnum\numppex=\@ne% + \ifexb@showLonelyPartProblems\else% + \global\exb@showCurrent@PPHeaderfalse% + \fi + \fi% + \fi% + \stepcounter{numppInFile}% +} +\At\EndProblem{% + \immediate\write\@auxout{\string\expandafter\string\gdef\string\csname\space exb@numexercises@\the\numexpr\the\c@problemcounter\endcsname{\the\c@numppInFile}}% + \setcounter{numppInFile}{0}% +} \providecommand\exb@currentTags{} +\providecommand\exb@nextprob@header{} \pgfkeys{/exbank/problems/.cd,% -default/.style={hide=false,tag=\relax},% +initial style/.style={hide=false,tag=\relax,reset pp head},% +default/.style={initial style}, hide/.is if={exb@opthides},% tags/.estore in=\exb@currentTags,% -tag/.code={\pgfkeysalso{tags={#1}}}% +tag/.code={\pgfkeysalso{tags={#1}}}, +head/.code={\global\exb@b@nextprob@headertrue\gdef\exb@nextprob@header{#1}},% +reset pp head/.code={\global\exb@b@nextprob@headerfalse}, +solution only/.code={\ifexb@DisplaySolutions\else\pgfkeysalso{/exbank/problems/hide=true}\fi}, +reset to default/.code=\pgfkeysalso{/exbank/problems/default/.style={initial style}} } \def\nextproblem{\pgfqkeys{/exbank/problems}} +\def\resetnextproblems{\nextproblem{reset to default}} +\def\nextproblems#1{% +\edef\nextprobargs{{default/.style={#1}}}% +\expandafter\nextproblem\nextprobargs% +} +\newcounter{exb@cutfilecounter} +\global\let\do@ProcessCutFile = \ProcessCutFile \At\EndProblem{% -\if\exbank@opt@tightenparagraphs\@isTrue\relax% - \if\@SolutionsOnly\@isFalse% - \if\@DisplaySolutions\@isTrue% - \penalty-300% - \fi% - \fi% -\fi% + \ifexb@opt@tightenparagraphs\relax% + \ifexb@DisplaySolutions% + \penalty-300% + \fi% + \fi% } -\@ifundefined{figure}{}{\edef\figure{\unexpanded{\tighten@paragraph@always}\unexpanded\expandafter{\figure}} +\@ifundefined{figure}{}{ \edef\figure{\unexpanded{\tighten@paragraph@always}\unexpanded\expandafter{\figure}} } -\@ifundefined{endfigure}{}{\g@addto@macro\endfigure{\tighten@paragraph@always} +\@ifundefined{endfigure}{}{ \g@addto@macro\endfigure{\tighten@paragraph@always} } \gdef\isFalse{0} \gdef\isTrue{1} -\gdef\DisplayProblem{\isTrue} +\global\exb@DisplayCurrentProblemtrue \gdef\@displayMetaCounter{\isFalse} -\AtBeginDocument{ \if\@DisplaySolutions\isFalse - \@latex@warning{Hiding solutions. Show them with \string\DisplaySolutions} - \fi +\AtBeginDocument{ \ifexb@DisplaySolutions\else + \@latex@warning{Hiding solutions. Show them with \string\DisplaySolutions} + \fi } -\global\let\do@ProcessCutFile = \ProcessCutFile \newif\ifexb@isdisplaying -\newif\ifexb@hidenextsol -\global\exb@hidenextsolfalse -\gdef\exb@ifshowproblem#1#2{\exb@isdisplayingfalse\ifnum\pdfstrcmp{\DisplayProblem}{\@isTrue}=\z@\ifexb@opthides\else\exb@isdisplayingtrue\fi\fi% -\ifexb@isdisplaying#1\else#2\fi} -\gdef\showhideproblem#1{% -\exb@ifshowproblem{\let\ProcessCutFile\do@ProcessCutFile#1\global\exb@hidenextsolfalse}{\def\ProcessCutFile{}\global\exb@hidenextsoltrue}% +\long\gdef\exb@ifshowproblem#1#2{% + \exb@isdisplayingfalse% + \ifexb@DisplayCurrentProblem% + \ifexb@opthides\else\exb@isdisplayingtrue\fi\fi% + \ifexb@isdisplaying#1\else#2\fi% +} +\long\gdef\showhideproblem#1{% + \exb@ifshowproblem{\let\ProcessCutFile\do@ProcessCutFile#1\global\exb@DisplayCurrentSolutiontrue}{\def\ProcessCutFile{}\global\exb@DisplayCurrentSolutionfalse}% } \generalcomment{problem}{% - \edef\DisplaySolution{\@DisplaySolutions}% - \stepcounter{metacounter}% - \@dinfo{problem: Triggering \string\DecideProblemDisplay}% - \Trigger\DecideProblemDisplay% - \@dinfo{problem:Executing - \string\showhideproblem}% - \showhideproblem{% - \if\exbank@opt@partProblems\isTrue - \Trigger\BeginPartproblem% - \Trigger\VeryBeginPartproblem% - \else% - \Trigger\BeginProblem% - \Trigger\VeryBeginProblem% - \fi% + \ifexb@DisplaySolutions + \global\exb@DisplayCurrentSolutiontrue\else\global\exb@DisplayCurrentSolutionfalse + \fi + \stepcounter{metacounter}% + \@dinfo{problem: Triggering \string\DecideProblemDisplay}% + \Trigger\DecideProblemDisplay% + \@dinfo{problem:Executing - \string\showhideproblem - \the\c@problemcounter}% + \showhideproblem{% + \ifexb@opt@partProblems% + \ifexb@solutionsonly\else + \Trigger\BeginPartproblem% + \Trigger\VeryBeginPartproblem% + \fi + \else% + \Trigger\BeginProblem% + \Trigger\VeryBeginProblem% + \fi% }% -}{\@dinfo{Ending problem env}% - \if\DisplayProblem\@isTrue\relax% - \if\exbank@opt@partProblems\@isTrue\relax% - \Trigger\EndPartproblem% - \tighten@paragraph\fi% - \else - \Trigger\EndProblem% - \fi% -\@dinfo{Ended problem env}% + \ifexb@solutionsonly\def\ProcessCutFile{}\ifexb@DisplayCurrentProblem\relax\stepcounter{partproblemcounter}\fi\fi +}{% + \@dinfo{Ending problem env \the\c@problemcounter}% + \ifexb@DisplayCurrentProblem\relax% + \ifexb@opt@partProblems\relax% + \Trigger\EndPartproblem% + \tighten@paragraph + \else + \Trigger\EndProblem% + \fi% + \fi% + \@dinfo{Ended problem env}% } \g@addto@macro\AfterproblemComment{\nextproblem{default}\ignorespaces}% -\generalcomment{solution}{\@dinfo{START solution ENV}% -\Trigger\AtBeginSolutionHard -\begingroup - \if\@DisplaySolutions\isTrue - \if\DisplayProblem\isFalse - \xdef\DisplaySolution{\isFalse} - \fi - \fi - \if\DisplaySolution\isTrue - \ifexb@hidenextsol\else\Trigger\BeginSolution\fi - \else - \def\ProcessCutFile{} - \fi +\generalcomment{solution}{% + \@dinfo{START solution ENV}% + \Trigger\AtBeginSolutionHard + \begingroup + \ifexb@DisplaySolutions% + \ifexb@DisplayCurrentProblem\else% + \global\exb@DisplayCurrentSolutionfalse + \fi + \else + \global\exb@DisplayCurrentSolutionfalse + \fi + \ifexb@DisplayCurrentSolution% + \let\ProcessCutFile\do@ProcessCutFile% + \ifexb@solutionsonly\AtNextPar{\leavevmode\smash{\llap{\exbank@opt@partProblemHeader}}\Trigger\AfterPPHeader}\fi% + \ifexb@DisplayCurrentSolution\Trigger\BeginSolution\fi% + \else + \def\ProcessCutFile{}% + \fi }{% -\if\DisplaySolution\isTrue -\Trigger\EndSolution -\tighten@paragraph@solutions -\vspace*{0.5em} -\fi -\endgroup -\Trigger\EndSolutionHard\@dinfo{END solution ENV}% + \ifexb@DisplayCurrentSolution% + \Trigger\EndSolution + \tighten@paragraph@solutions + \vspace{0.5em} + \fi + \endgroup + \Trigger\EndSolutionHard\@dinfo{END solution ENV}% } \g@addto@macro\AftersolutionComment{\ignorespaces} -\def\intromargin#1{% -\if\exbank@opt@doMargins\@isTrue% -\gdef\endintromargin{\endlist\endgroup}% -\begingroup\list{}{\leftmargin#1}\item[]% -\else% -\relax\global\let\endintromargin=\relax\fi% +\def\exb@intromargin{% + \ifexb@opt@doMargins\relax% + \gdef\exb@endintromargin{\endlist\endgroup}% + \begingroup\list{}{\leftmargin-\introOutdent}\item[]% + \else% + \relax\global\let\exb@endintromargin=\relax\fi% } \generalcomment{intro}{\@dinfo{START intro ENV}% - \if\@countIntros\isTrue% - \stepcounter{metacounter}% - \Trigger\DecideProblemDisplay% - \gdef\exb@pre@intro{}% - \gdef\exb@post@intro{}% - \if\@displayMetaCounter\isTrue\relax% - \gdef\exb@pre@intro{{\leavevmode{\llap{{\Large\themetacounter}:\hspace*{-\pMarginLeft}}}}\ignorespaces}% - \fi% - \if\exb@showtags\isTrue% - \xdef\exb@post@intro{\exb@printCurrentTags}% - \fi% - \if\@spriteMode\@isTrue% - \if\introarg\@isTrue% - \stepcounter{partproblemcounter}% - \fi% - \fi% - \gdef\@displayIntro{\@isFalse} - \showhideproblem{% - \tighten@paragraph% - \Trigger\BeginIntro\exb@pre@intro\exb@post@intro% - \gdef\@displayIntro{\@isTrue} + \ifexb@CountIntros% + \stepcounter{metacounter}% + \Trigger\DecideProblemDisplay% + \gdef\exb@pre@intro{}% + \gdef\exb@post@intro{}% + \if\@displayMetaCounter\isTrue\relax% + \gdef\exb@pre@intro{{\leavevmode{\llap{{\Large\themetacounter}:\hspace*{-\pMarginLeft}}}}\ignorespaces}% + \fi% + \ifexb@showtags% + \xdef\exb@post@intro{\exb@printCurrentTags}% + \fi% + \if\@spriteMode\@isTrue% + \if\introarg\@isTrue% + \stepcounter{partproblemcounter}% + \fi% + \fi% + \gdef\@displayIntro{\@isFalse}% + \showhideproblem{% + \tighten@paragraph% + \Trigger\BeginIntro\exb@pre@intro\exb@post@intro% + \gdef\@displayIntro{\@isTrue}% }% - \exb@ifshowproblem{\intromargin{-1em}}{} - \else% - \intromargin{-1em} - \fi% -}{ \if\@countIntros\isTrue% - \Trigger\EndIntro% - \exb@ifshowproblem{\endintromargin}{} - \else - \endintromargin - \fi% - \@dinfo{END intro ENV}\ignorespaces% + \exb@ifshowproblem{\exb@intromargin}{}% + \else% + \exb@intromargin% + \fi% + \ifexb@solutionsonly\def\ProcessCutFile{}\fi +}{ \ifexb@CountIntros% + \Trigger\EndIntro% + \exb@ifshowproblem{\exb@endintromargin}{} + \else + \exb@endintromargin + \fi% + \@dinfo{END intro ENV}\ignorespaces% } \g@addto@macro\AfterintroComment{\nextproblem{default}\ignorespaces} \def\squeeze{ \newlength{\marginw} @@ -504,18 +664,18 @@ tag/.code={\pgfkeysalso{tags={#1}}}% \global\exb@tagbuildmodefalse \global\let\emptyList\exb@emptyList \global\let\exb@tagList\exb@emptyList -\gdef\ifppMode#1{ \def\mname{\exbank@macroname{#1}} - \strif\mname\ppMode +\gdef\ifppMode#1{ \def\mname{\exbank@macroname{#1}} + \strif\mname\ppMode } -\gdef\isppMode#1#2{ \edef\mname{\exbank@macroname{#1}} - \strif{\exbank@macroname{#1}}{\ppMode}\relax#2\fi + \gdef\isppMode#1#2{ \edef\mname{\exbank@macroname{#1}} + \strif{\exbank@macroname{#1}}{\ppMode}\relax#2\fi } \gdef\@ifppMode#1{% -\ifnum\pdfstrcmp{\exbank@macroname{#1}}{\ppMode}=\z@% -\expandafter\@firstofone% -\else% -\expandafter\@noneofone% -\fi% + \ifnum\pdfstrcmp{\exbank@macroname{#1}}{\ppMode}=\z@% + \expandafter\@firstofone% + \else% + \expandafter\@noneofone% + \fi% }% \def\pm@Exclude{exclude} \def\pm@Select{select} @@ -523,84 +683,93 @@ tag/.code={\pgfkeysalso{tags={#1}}}% \let\ipm\@ifppMode \let\T@\isTrue \let\F@\isFalse +\def\exb@DPT{\global\exb@DisplayCurrentProblemtrue} +\def\exb@DPF{\global\exb@DisplayCurrentProblemfalse} \At\DecideProblemDisplay{% - \ifnum\pdfstrcmp{\ppList}{\emptyList}=\z@\relax% - \xdef\DisplayProblem{\ipm\exclude\T@\ipm\select\F@} - \fi - \exb@int@isin{\themetacounter}{\ppList}{ \xdef\DisplayProblem{\ipm\exclude\F@\ipm\select\T@\ipm\normal\T@} -}{ \xdef\DisplayProblem{\ipm\exclude\T@\ipm\select\F@\ipm\normal\T@} -} -\ifexb@tagbuildmode -\ifnum\pdfstrcmp{\DisplayProblem}{\T@}=\z@\relax% -\exb@intersection@any{\exb@currentTags}{\exb@tagList}{\global\exb@opthidesfalse}{\global\exb@opthidestrue\xdef\DisplayProblem{0}}% -\fi -\fi + \ifnum\pdfstrcmp{\ppList}{\emptyList}=\z@\relax% + \ipm\exclude\exb@DPT\ipm\select\exb@DPF + \fi + \exb@int@isin{\themetacounter}{\ppList}{ \ipm\exclude\exb@DPF\ipm\select\exb@DPT\ipm\normal\exb@DPT +}{ \ipm\exclude\exb@DPT\ipm\select\exb@DPF\ipm\normal\exb@DPT +} + \ifexb@tagbuildmode + \ifexb@DisplayCurrentProblem\relax% + \exb@intersection@any{\exb@currentTags}{\exb@tagList}{\global\exb@opthidesfalse}{\global\exb@opthidestrue\global\exb@DisplayCurrentProblemfalse}% + \fi + \fi } \gdef\introarg{\@isFalse} -\gdef\noheadarg{\@isFalse} -\pgfkeys{ /makeset/.is family, /makeset, - default/.style = {}, - intro/.style = {introarg=\@isTrue}, - nointro/.style = {introarg=\@isFalse}, - nohead/.style = {noheadarg=\@isTrue}, - head/.style = {noheadarg=\@isFalse}, - introarg/.estore in = \introarg, - noheadarg/.estore in = \noheadarg +\pgfkeys{ /makeset/.is family, /makeset, + default/.style = {noheadarg=false}, + intro/.style = {introarg=\@isTrue}, + nointro/.style = {introarg=\@isFalse}, + nohead/.style = {noheadarg=true}, + head/.style = {noheadarg=false}, + introarg/.estore in = \introarg, + noheadarg/.is if = {exb@noheadArg}, } \gdef\makesetdefaults#1{% -\edef\exb@setpgfkeys{{\unexpanded\expandafter{/makeset/default/.style = {#1}}}}% -\expandafter\pgfkeys\exb@setpgfkeys% + \edef\exb@setpgfkeys{{\unexpanded\expandafter{/makeset/default/.style = {#1}}}}% + \expandafter\pgfkeys\exb@setpgfkeys% } \pgfkeys{/makeset/override/.cd, -intro/.code = {\gdef\introarg{\@isTrue}\ea\gdef\csname setlist@\exb@currentSetID @intro\endcsname{\@isTrue}}, -nointro/.code = {\gdef\introarg{\@isFalse}\ea\gdef\csname setlist@\exb@currentSetID @intro\endcsname{\@isFalse}}, -nohead/.code = {\gdef\noheadarg{\@isTrue}\ea\gdef\csname setlist@\exb@currentSetID @nohead\endcsname{\@isTrue}} + intro/.code = {\gdef\introarg{\@isTrue}\ea\gdef\csname setlist@\exb@currentSetID @intro\endcsname{\@isTrue}}, + nointro/.code = {\gdef\introarg{\@isFalse}\ea\gdef\csname setlist@\exb@currentSetID @intro\endcsname{\@isFalse}}, + nohead/.code = {\exb@noheadArgtrue\ea\gdef\csname setlist@\exb@currentSetID @nohead\endcsname{\@isTrue}} } \gdef\@listOfSets{} \gdef\@spriteMode{\isFalse} \gdef\exbank@spriteSets{\emptyList} -\long\gdef\spritesets#1{ \gdef\exbank@spriteSets{#1} -} -\global\let\exlist@protect\noexpand -\newcommand\makeset[3][]{ \xdef\thissetid{#2} - \ea\xdef\csname setkeys@\thissetid\endcsname{#1} - \pgfkeys{/makeset, default, #1}% - \if\introarg\isTrue% - \gdef\introarg{\isTrue} - \ea\gdef\csname setlist@#2@intro\endcsname{\isTrue} - \fi - \if\noheadarg\isTrue% - \ea\gdef\csname setlist@#2@nohead\endcsname{\isTrue} - \fi - \ea\gdef\csname setlist@#2\endcsname{\exlist@protect{#3}} - \def\setmacro{\unexpanded\expandafter{\csname setlist@#2\endcsname}} - \g@addto@macro\@listOfSets{,#2} +\long\gdef\spritesets#1{ \gdef\exbank@spriteSets{#1} +} +\gdef\exb@listofsetnames{} +\global\let\exlist@protect\unexpanded +\newcommand\makeset[3][]{ \xdef\thissetid{#2} + \xdef\exb@listofsetnames{\unexpanded\expandafter{\exb@listofsetnames}\thissetid,} + \ea\xdef\csname setkeys@\thissetid\endcsname{#1} + \pgfkeys{/makeset, default, #1}% + \if\introarg\isTrue% + \gdef\introarg{\isTrue} + \ea\gdef\csname setlist@#2@intro\endcsname{\isTrue} + \fi + \ifexb@noheadArg% + \ea\gdef\csname setlist@#2@nohead\endcsname{\isTrue} + \fi + \ea\gdef\csname setlist@#2\endcsname{\exlist@protect{#3}} + \def\setmacro{\unexpanded\expandafter{\csname setlist@#2\endcsname}} + \g@addto@macro\@listOfSets{,#2} } \long\gdef\about#1{} +\newcommand\buildall{% +\edef\tmpargs{{\exb@listofsetnames}} +\dlog{\tmpargs} +\expandafter\buildsets\tmpargs +} \newcommand\sprite[1][4]{\squeeze \gdef\@spriteMode{\isTrue} \long\def\about##1{{\Large\textbf{About}:\\[1.1em]##1\\[1.5em]}} \pgfpagesuselayout{#1 on 1}[a4paper,border shrink=5mm] \ifnum\pdfstrcmp{\exbank@spriteSets}{\emptyList}=\z@\relax% - \edef\sprite@setlist{\ea\@secondoftwo\@listOfSets} - \readlist*\list@sprite@setlist\sprite@setlist - \foreachitem\set\in\list@sprite@setlist{ \edef\theset{{\set}} - \if\theset\empty\relax\else% - \buildset{\set}% - \fi% + \edef\sprite@setlist{\ea\@secondoftwo\@listOfSets} + \readlist*\list@sprite@setlist\sprite@setlist + \foreachitem\set\in\list@sprite@setlist{ \edef\theset{{\set}} + \if\theset\empty\relax\else% + \buildset{\set}% + \fi% } \else - \edef\sprite@setlist{\exbank@spriteSets} - \readlist*\list@sprite@setlist\sprite@setlist - \foreachitem\set\in\list@sprite@setlist{ \edef\theset{{\set}} - \if\theset\empty\relax\else% - \buildex{\set}% - \fi% + \edef\sprite@setlist{\exbank@spriteSets} + \readlist*\list@sprite@setlist\sprite@setlist + \foreachitem\set\in\list@sprite@setlist{ \edef\theset{{\set}} + \if\theset\empty\relax\else% + \buildex{\set}% + \fi% } \fi } \gdef\exbank@setEnv@normal#1{\exbank@setEnv{#1}{normal} } +\gdef\exerciseFile{}% \newcommand{\exbank@setEnv}[3][{-1}]{ \if\@spriteMode\isFalse% \gdef\ppList{#1} \gdef\exerciseFile{#2} @@ -611,31 +780,32 @@ nohead/.code = {\gdef\noheadarg{\@isTrue}\ea\gdef\csname setlist@\exb@currentSet \gdef\ppMode{\pm@Normal} \fi } +\global\let\exb@execChar\relax \global\let\ex@protect\noexpand -\long\gdef\exec#1{:\ex@protect{#1}} -\gdef\exb@def@makeset@cmd#1{\@ifnextchar[{\@exb@def@makeset@cmd{#1}}{\@exb@def@makeset@cmd{#1}[0]}} -\gdef\@exb@def@makeset@cmd#1[#2]#3{\def\ncArgs{#1[#2]}% +\long\gdef\exec#1{\exb@execChar\ex@protect{#1}} +\long\gdef\exb@def@makeset@cmd#1{\@ifnextchar[{\@exb@def@makeset@cmd{#1}}{\@exb@def@makeset@cmd{#1}[0]}} +\long\gdef\@exb@def@makeset@cmd#1[#2]#3{\def\ncArgs{#1[#2]}% \bgroup\globaldefs=1\ea\newcommand\ncArgs{\exec{#3}}\egroup% } -\def\exbank@def@makeset@command{\exb@warn{\string\exbank@def@makeset@command\space is deprecated and will be removed in versions >= 0.3.0. Use \string\exb@def@makeset@cmd}\exb@def@makeset@cmd} +\def\exbank@def@makeset@command{\exb@warn{\string\exbank@def@makeset@command\space is deprecated and will be removed in versions >= 0.3.0. Use \string\exb@def@makeset@cmd\space(or \string\DeclareExerciseCommand where applicable)}\exb@def@makeset@cmd} \let\DeclareExerciseCommand\exb@def@makeset@cmd \newcommand{\exclude}[2]{[{#2}]{#1}{exclude}} \newcommand{\select}[2]{[{#2}]{#1}{select}} \newcommand{\orderedselect}[2]{% -\readlist*\thelist\csv@list% -\foreachitem\items\in\thelist{[{\item}]{#1},}% } -\let\exbank@isFirstProblem\isTrue -\exb@def@makeset@cmd{\phead}{ \if\exbank@isFirstProblem\isTrue% - \let\exbank@isFirstProblem\isFalse% +\exb@isFirstProblemtrue +\exb@def@makeset@cmd{\phead}{% + \ifexb@isFirstProblem% + \global\exb@isFirstProblemfalse% \else% \Trigger\EndProblem% \fi% +\par% \Trigger\BeginProblem% \Trigger\VeryBeginProblem% } -\exb@def@makeset@cmd{\pheadarg}[1]{ \if\exbank@isFirstProblem\isTrue% - \let\exbank@isFirstProblem\isFalse% +\exb@def@makeset@cmd{\pheadarg}[1]{ \ifexb@isFirstProblem% + \global\exb@isFirstProblemfalse% \else% \Trigger\EndProblem% \fi% @@ -643,91 +813,109 @@ nohead/.code = {\gdef\noheadarg{\@isTrue}\ea\gdef\csname setlist@\exb@currentSet \bgroup\def\theproblemcounter{#1}\Trigger\VeryBeginProblem\egroup% } \exb@def@makeset@cmd{\pbreak}{\clearpage} -\gdef\buildex#1{ \makeset{#1}{#1} - \buildset{#1} +\gdef\buildex#1{ \makeset{#1}{#1} + \buildset{#1} } -\gdef\@countIntros{\isFalse} +\exb@CountIntrosfalse \gdef\exb@setpgf#1{% -\edef\keystring{{/makeset,default,#1}}% -\ea\pgfkeys\keystring} + \edef\keystring{{/makeset,default,#1}}% + \ea\pgfkeys\keystring} +\long\def\exb@getnextchar#1#2\endstr{\gdef\exb@nextchar{#1}\gdef\exb@restchars{#2}} +\long\gdef\@execute@makeset@command#1{% + \@dinfo{Executing macro \@backslashchar\@gobble##1}% + \csname #1\endcsname% + \def\continueLoop{\isFalse}% +} +\long\def\@execute@exec#1{% + \def\continueLoop{\isFalse}\@dinfo{Executing custom (\string\exec) command}{#1}% +} +\long\gdef\X@exb@setEnv#1{% + \def\continueLoop{\isTrue}% + \@dinfo{Processing normal file "\exerciseFileInfo.tex"}% + \exbank@setEnv@normal{#1}% +} +\long\gdef\exb@setEnv@withOptargs#1{% + \def\continueLoop{\isTrue} + \edef\firstarg{#1} + \expandafter\exbank@setEnv\firstarg% +} +\def\set@charcode#1{\edef\testcode{\unexpanded{\the\numexpr`}#1}} +\long\def\@delegateFileInfo#1{% + \expandafter\exb@getnextchar#1\endstr% + \set@charcode\exb@nextchar\relax + \ifnum\testcode=\the\numexpr`?\relax + \relax\@execute@makeset@command\exb@restchars% + \else\ifnum\testcode = \the\numexpr`:\relax% + \@execute@exec\exb@restchars + \else\ifnum\testcode = \the\numexpr`[\relax% + \exb@setEnv@withOptargs{\exb@nextchar\exb@restchars} + \else% + \X@exb@setEnv{\exb@nextchar\exb@restchars} + \fi + \fi + \fi +} \newcommand\buildset[2][]{% - \xdef\exb@currentSetID{#2}% - \pgfkeys{/makeset/override/.cd, #1} - \global\let\setName\exb@currentSetID% - \gdef\exb@buildset@oarg{#1} - \@ifundefined{setlist@#2@intro}{\gdef\@countIntros{\isFalse}}{\gdef\@countIntros{\isTrue}}% - \@ifundefined{setlist@#2@nohead}{\gdef\nohead{\isFalse}}{\gdef\nohead{\isTrue}}% - \ifcsname setkeys@\setName\endcsname% - \xdef\skeys{\csname setkeys@#2\endcsname}% - \exb@setpgf\skeys% - \fi% - \@ifundefined{setlist@#2}{% - \@latex@error{Couldn't find set #2. Did you remember to do \string\makeset{#2}{}?} - \stop\bye + \xdef\exb@currentSetID{#2}% + \pgfkeys{/makeset/override/.cd, #1} + \global\let\setName\exb@currentSetID% + \gdef\exb@buildset@oarg{#1} + \@ifundefined{setlist@#2@intro}{\exb@CountIntrosfalse}{\exb@CountIntrostrue}% + \@ifundefined{setlist@#2@nohead}{\gdef\nohead{\isFalse}}{\gdef\nohead{\isTrue}}% + \ifcsname setkeys@\setName\endcsname% + \xdef\skeys{\csname setkeys@#2\endcsname}% + \exb@setpgf\skeys% + \fi% + \@ifundefined{setlist@#2}{% + \exb@err{Couldn't find set #2. Did you remember to do \string\makeset{#2}{}?} + \stop\bye }{} - \let\exlist@protect\unexpanded% - \edef\exbank@setlist{\csname setlist@#2\endcsname}% - \let\exlist@protect\noexpand% - \if\@spriteMode\isFalse% - \if\exb@frontpage\@isFalse\else\input{\exb@frontpage}\fi - \Trigger\StartBuildset% - \fi% - \gdef\@delegateFileInfo{\@ifnextchar?\@execute@makeset@command\@is@exec}% - \def\@is@exec{\@ifnextchar:\@execute@exec\@is@file}% - \gdef\@is@file{\@ifnextchar[\exb@setEnv@withOptargs\X@exb@setEnv}% - \gdef\X@exb@setEnv##1{% - \def\continueLoop{\isTrue}% - \@dinfo{Processing normal file "\exerciseFileInfo.tex"}% - \exbank@setEnv@normal{\exerciseFileInfo}\bgroup\nullfont% -} - \gdef\exb@setEnv@withOptargs{% - \def\continueLoop{\isTrue}\ea\exbank@setEnv\exerciseFileInfo\bgroup\nullfont% -} - \gdef\@execute@makeset@command ?##1{% - \edef\inner{\@firstofone##1}% - \@dinfo{Executing macro \@backslashchar\@gobble##1}% - \csname\inner\endcsname% - #1\def\continueLoop{\isFalse}\ea\bgroup% -} - \def\@execute@exec:{% - \def\continueLoop{\isFalse}\@dinfo{Executing custom command}\bgroup% -} - \readlist*\setlist\exbank@setlist% - \foreachitem\exerciseFileInfo\in\setlist{% - \def\continueLoop{\isTrue}% - \gdef\ppList{\emptyList}% - \setcounter{metacounter}{0}% - \let\ex@protect\unexpanded% - \edef\exerciseFileInfo{\exerciseFileInfo}% - \ea\@delegateFileInfo\exerciseFileInfo\egroup% - \Trigger\InputExercise% - \if\continueLoop\isTrue% - \let\ex@protect\noexpand% - \Trigger\PathControl% - \if\nohead\isFalse% - \if\@spriteMode\isFalse% - \Trigger\BeginProblem% - \fi% - \fi% - \if\nohead\isFalse\Trigger\VeryBeginProblem\fi% - \if\@spriteMode\isTrue\textbf{\exerciseFile.tex\\}\fi% - \IfFileExists{\@exercisesDir/\exerciseFile}{% - \incl{\@exercisesDir/\exerciseFile}% - \if\@spriteMode\isTrue% - \setcounter{partproblemcounter}{0}% - \fi% -}{ \@latex@error{Could not find \@exercisesDir/\exerciseFile. Maybe it is because the default exercise directory is now changed to the same directory that your main file is in. To set default exercise directory to exercises, do \string\exercisebanksetup{exercise directory=exercises}}{} - \stop\bye -} - \if\nohead\isFalse\Trigger\EndProblem\fi% - \fi% + \let\exlist@protect\unexpanded% + \edef\exbank@setlist{\csname setlist@#2\endcsname}% + \let\exlist@protect\unexpanded% + \if\@spriteMode\isFalse% + \if\exb@frontpage\@isFalse\else\input{\exb@frontpage}\fi + \Trigger\StartBuildset% + \fi% + \readlist*\setlist\exbank@setlist% + \foreachitem\exerciseFileInfo\in\setlist{% + \def\continueLoop{\isTrue}% + \gdef\ppList{\emptyList}% + \setcounter{metacounter}{0}% + \let\ex@protect\unexpanded% + \edef\exb@execChar{:}% + \edef\exerciseFileInfo{\exerciseFileInfo}% + \@delegateFileInfo\exerciseFileInfo% + \Trigger\InputExercise% + \if\continueLoop\isTrue% + \let\ex@protect\noexpand% + \Trigger\PathControl% + \if\nohead\isFalse% + \if\@spriteMode\isFalse% + \Trigger\BeginProblem% + \fi% + \fi% + \if\nohead\isFalse\Trigger\VeryBeginProblem\fi% + \if\@spriteMode\isTrue\textbf{\exerciseFile.tex\\}\fi% + \IfFileExists{\@exercisesDir/\exerciseFile}{% + \Trigger\InputExerciseFile + \let\exb@execChar\relax + \incl{\@exercisesDir/\exerciseFile}% + \if\@spriteMode\isTrue% + \setcounter{partproblemcounter}{0}% + \fi% +}{ \@latex@error{Could not find \@exercisesDir/\exerciseFile. Maybe it is because the default exercise directory is now changed to the same directory that your main file is in. To set default exercise directory to exercises, do \string\exercisebanksetup{exercise directory=exercises}}{} + \stop\bye +} + \if\nohead\isFalse\Trigger\EndProblem\fi% + \fi% } - \if\@spriteMode\isFalse% - \Trigger\EndBuildset% - \fi% - \setcounter{problemcounter}{0}% - \setcounter{partproblemcounter}{0}% - \clearpage% + \if\@spriteMode\isFalse% + \Trigger\EndBuildset% + \fi% + \setcounter{problemcounter}{0}% + \setcounter{partproblemcounter}{0}% + \clearpage% } \newcommand\buildsets[2][]{% \xdef\csvlist{#2}% @@ -737,22 +925,27 @@ nohead/.code = {\gdef\noheadarg{\@isTrue}\ea\gdef\csname setlist@\exb@currentSet } } \newcommand\buildtags[2]{% - \global\exb@tagbuildmodetrue - \xdef\csvtags{#1}% - \xdef\csvlist{#2} + \global\exb@tagbuildmodetrue + \xdef\csvtags{#1}% + \xdef\csvlist{#2} \xdef\csvsets{#2}% \readlist*\tagsItems\csvtags% - \readlist*\setsItems\csvsets% + \readlist*\setsItems\csvsets% \foreachitem\set\in\setsItems{% - \xdef\exb@tagList{\csvtags} + \xdef\exb@tagList{\csvtags} \buildset{\set}% } - \global\exb@tagbuildmodefalse + \global\exb@tagbuildmodefalse +} +\def\buildsprite#1{\squeeze% +\gdef\@spriteMode{\isTrue} +\pgfpagesuselayout{4 on 1}[a4paper,border shrink=5mm]% +\buildsets{#1}% } -\newcommand\refcounter[1]{\edef\@currentlabel{#1}% +\providecommand\refcounter[1]{\edef\@currentlabel{#1}% } -\DeclareRobustCommand{\pplabel}[1]{ \refcounter{\theproblemcounter}\label{pr:\exerciseFile:#1} - \refcounter{\alph{partproblemcounter}}\label{pp:\exerciseFile:#1} +\DeclareRobustCommand{\pplabel}[1]{ \refcounter{\theproblemcounter}\label{pr:\exerciseFile:#1}\label{pr:global:#1} + \refcounter{\alph{partproblemcounter}}\label{pp:\exerciseFile:#1}\label{pp:global:#1} } \let\pptag = \pplabel \newcommand\pppref[1]{% @@ -761,34 +954,77 @@ nohead/.code = {\gdef\noheadarg{\@isTrue}\ea\gdef\csname setlist@\exb@currentSet \newcommand\ppref[1]{% (\ref{pr:\exerciseFile:#1}\ref{pp:\exerciseFile:#1})\relax% } +\newcommand\ppgref[1]{% +(\ref{pr:global:#1}\ref{pp:global:#1})\relax% +} \newcommand\pref[1]{% \ref{pr:\exerciseFile:#1}\relax% } +\newcommand\pgref[1]{% +\ref{pr:global:#1}\relax% +} \gdef\exb@currentPoints{0} \gdef\exb@currentPointsStyle{} \newif\ifexb@enablepoints\global\exb@enablepointstrue \exercisebanksetup{% -current points style/.store in=\exb@currentPointsStyle, -current points style={\ifnum\exb@currentPoints=\z@\ifnum\totalpoints=\z@\else\phantom{0p}\fi\else\exb@currentPoints p\fi\ignorespaces}, -disable points/.is if={exb@enablepoints} + current points style/.store in=\exb@currentPointsStyle, + current points style={\ifnum\exb@currentPoints=\z@\ifnum\totalpoints=\z@\else\phantom{0p}\fi\else\exb@currentPoints p\fi\ignorespaces}, + disable points/.is if={exb@enablepoints} } \ifexb@enablepoints -\AtEndDocument{% -\immediate\write\@auxout{\string\gdef\string\totalpoints{\the\c@exb@points}}% + \AtEndDocument{% + \immediate\write\@auxout{\string\gdef\string\totalpoints{\the\c@exb@points}}% } -\At\PartProblemHeaderSuffix{\exb@currentPointsStyle} + \At\PartProblemHeaderSuffix{\exb@currentPointsStyle} \fi \newcounter{exb@points} \setcounter{exb@points}{0} \providecommand\totalpoints{} \nextproblem{points/.store in=\exb@currentPoints} -\At\BeginPartproblem{\addtocounter{exb@points}\exb@currentPoints} +\At\BeginPartproblem{% +\addtocounter{exb@points}{\exb@currentPoints}% +} \At\EndPartproblem{\gdef\exb@currentPoints{0}} +\providecommand\exercisepoints{} +\newcounter{exb@tmp@exercisepoints} +\setcounter{exb@tmp@exercisepoints}{0} +\At\VeryBeginProblem{ \xdef\exb@expoints@macname{exb@exercisepoints@\the\c@problemcounter} + \ifcsname\exb@expoints@macname\endcsname% + \xdef\exercisepoints{\csname\exb@expoints@macname\endcsname} + \else% + \gdef\exercisepoints{} + \fi + \setcounter{exb@tmp@exercisepoints}{0} +} +\At\BeginPartproblem{% +\addtocounter{exb@tmp@exercisepoints}{\exb@currentPoints}% +} +\At\EndProblem{% +\immediate\write\@auxout{\string\expandafter\string\gdef\string\csname\space exb@exercisepoints@\the\numexpr\the\c@problemcounter\endcsname{\the\c@exb@tmp@exercisepoints}}% +} \def\exb@hidetaglist{} -\At\DecideProblemDisplay{\ifnum\pdfstrcmp{\DisplayProblem}{\T@}=\z@\relax% -\ifx\exb@hidetaglist\relax\else -\exb@intersection@any{\exb@currentTags}{\exb@hidetaglist}{\global\exb@opthidestrue}{\global\exb@opthidesfalse}% +\At\DecideProblemDisplay{\ifexb@DisplayCurrentProblem\relax% +\ifx\exb@hidetaglist\empty\relax\else +\exb@intersection@any{\exb@currentTags}{\exb@hidetaglist}{\global\exb@opthidestrue}{}% +\fi \fi +} +\gdef\HideTags#1{\xdef\exb@hidetaglist{\unexpanded\expandafter{\exb@hidetaglist},#1}} +\gdef\ShowAllTags{\gdef\exb@hidetaglist{}} +\global\let\@exercisenote\@nil% +\gdef\@addExercisenote#1{% + \ifx\@exercisenote\@@nil% + \gdef\@exercisenote{#1}% + \else + \g@addto@macro{\@exercisenote}{\par#1} \fi } -\gdef\HideTags#1{\xdef\exb@hidetaglist{#1}} +\At\VeryBeginProblem{% +\ifx\@exercisenote\@@nil\else% +\begingroup\list{}{\leftmargin-\introOutdent}\item[]% +\@exercisenote% +\endlist\endgroup% +\global\let\@exercisenote\nil% +\fi% +} +\DeclareExerciseCommand\exercisenote[1]{\@addExercisenote{#1}} -- cgit v1.2.3