% Pseudocodex Algorithmic Style % % Copyright 2017 Christian Matt % Based on Szasz Janos' algpseudocode.sty % \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{algpseudocodex} \RequirePackage{algorithmicx} \RequirePackage{etoolbox} \RequirePackage{fifo-stack} \RequirePackage{varwidth} \RequirePackage{tikz} \usetikzlibrary{calc,fit,tikzmark} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Package options % \newbool{algpx@noEnd} \newbool{algpx@indLine} \DeclareOption{noend}{\setbool{algpx@noEnd}{true}} \DeclareOption{end}{\setbool{algpx@noEnd}{false}} \DeclareOption{noindline}{\setbool{algpx@indLine}{false}} \DeclareOption{indline}{\setbool{algpx@indLine}{true}} \ProcessOptions* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Styles % \tikzset{% defaultCodeBox/.style={draw},% algpxIndentLine/.style={draw=lightgray,very thin}% } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Declarations % \algnewlanguage{pseudocodex} \alglanguage{pseudocodex} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Macros for boxes around code % % \tikzmark is only available on next compilation; the following command immediately after using it \newcommand{\@tikzmarkNow}[2][]{\tikz[overlay,remember picture] \node[#1] (#2) {};} \long\def\@ifnodedefined#1#2#3{% \@ifundefined{pgf@sh@ns@#1}{#3}{#2}% } \newlength{\algpx@codeBoxInnerSep}% distance between box and its content \newlength{\algpx@codeBoxSep}% distance between nested boxes \newlength{\algpx@codeBoxOuterSep}% additional space before and after box \newlength{\algpx@minIndDist}% minimum distance between start and end of indent line to draw line \setlength{\algpx@codeBoxInnerSep}{2pt} \setlength{\algpx@codeBoxSep}{3pt} \setlength{\algpx@codeBoxOuterSep}{1pt} \newbool{algpx@firstLine} \newbool{algpx@setNorth} \newbool{algpx@executeEndVarwidth} \newbool{algpx@adjustHeight} \newbool{algpx@restorePrevdepth} \newcounter{algpx@codeBoxCount} \newcounter{algpx@nestedCBoxCount} \newcounter{algpx@startedBoxesCount} \newcounter{algpx@endedBoxesCount} \newcounter{algpx@nestedBoxedStringCount} \newcounter{algpx@nestedBoxedStringMaxCount} \newlength{\algpx@oldPos} \newlength{\algpx@newPos} \newlength{\algpx@tmpLen} \FSCreate{algpx@startNewCodeBoxQueue}{0} \FSCreate{algpx@codeBoxStack}{0} \FSCreate{algpx@codeBoxStackTmp}{0} \newsavebox{\algpx@boxedStringBox} \newcommand{\algpx@drawCodeBox}[5]{% \tikz[overlay,remember picture]{% \node[inner sep=\algpx@codeBoxInnerSep,#1,fit={(pic cs:#2) (pic cs:#3) (pic cs:#4) (pic cs:#5)}] {};% }% } % execute after \State, \If etc. \newcommand{\algpx@startCodeCommand}{% \setbool{algpx@indJustEnded}{false}% \setcounter{algpx@startedBoxesCount}{0}% \setcounter{algpx@endedBoxesCount}{0}% \setcounter{algpx@nestedBoxedStringMaxCount}{0}% \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{% \FSPush{algpx@codeBoxStack}{\FSTop{algpx@startNewCodeBoxQueue}}% \algpx@drawCodeBox{algpx@codeBoxStyle\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxNorth-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxWest-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxEast-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxSouth-\FSTop{algpx@startNewCodeBoxQueue}}% \FSPop{algpx@startNewCodeBoxQueue}% \setbool{algpx@setNorth}{true}% \stepcounter{algpx@startedBoxesCount}% }% \algpx@setCodeBoxWest% \setbool{algpx@firstLine}{false}% \setbool{algpx@executeEndVarwidth}{true}% % create box from here to end of line \begin{varwidth}[t]{\dimexpr \linewidth - \algorithmicindent * \numexpr \value{ALG@nested} - 1 \relax \relax}% } % executed before \State, \If etc., i.e., at end of previous line % first argument 1 if after \EndIf etc. and noend \newcommand{\algpx@endCodeCommand}[1][0]{% \ifbool{algpx@executeEndVarwidth}{% \par\xdef\algpx@pdtemp{\the\prevdepth}% see https://tex.stackexchange.com/a/34982 \end{varwidth}\setbox0=\lastbox\usebox0% \setbool{algpx@executeEndVarwidth}{false}% \setbool{algpx@adjustHeight}{true}% \setbool{algpx@restorePrevdepth}{true}% }{}% \ifbool{algpx@setNorth}{% % todo: north should not be set again if highest element in current line is BoxedString \algpx@setCodeBoxNorth{\the\ht0}% set north here shifted by height of current line \setbool{algpx@setNorth}{false}% }{}% \algpx@setCodeBoxEast% \ifbool{algpx@adjustHeight}{% % todo: if highest or deepest element in current line is BoxedString, \ht0 or \dp0 should be adjusted for different sep values \algpx@addBoxSpacing{\value{algpx@startedBoxesCount}}{\the\ht0}{\value{algpx@endedBoxesCount}}{\the\dp0}% \setbool{algpx@adjustHeight}{false}% }{}% \ifboolexpr{bool{algpx@restorePrevdepth} and test{\ifstrequal{#1}{0}}}{% \par\prevdepth\algpx@pdtemp% \setbool{algpx@restorePrevdepth}{false}% }{}% } % set algpx@codeBoxNorthMax of current box and all ancestors; argument is amount to shift up from current baseline \newcommand{\algpx@setCodeBoxNorth}[1]{% \setcounter{algpx@nestedCBoxCount}{0}% \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp \@ifnodedefined{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}{% % get current position; shift according to nest-level to ensure nested boxes don't collide \@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthHere}% % extract y-coordinate of previously stored north \tikz[overlay,remember picture]{% \pgfextracty{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}{center}}% \pgfextracty{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxNorthHere}{center}}% \global\algpx@oldPos=\algpx@oldPos% \global\algpx@newPos=\algpx@newPos% }% \ifdimcomp{\algpx@oldPos}{<}{\algpx@newPos}{% % new y is greater than old one, so set it \@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}% }{% \@tikzmarkNow{algpx@codeBoxNorthDummy}% set something to keep in sync }% }{% \@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}% }% \FSPop{algpx@codeBoxStack}% \stepcounter{algpx@nestedCBoxCount}% }% % restore stack from tmp \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% \FSPop{algpx@codeBoxStackTmp}% }% } % set algpx@codeBoxSouthMax of current box and all ancestors; argument is amount to shift down from current baseline \newcommand{\algpx@setCodeBoxSouth}[1]{% \setcounter{algpx@nestedCBoxCount}{0}% \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp \@ifnodedefined{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}{% % get current position; shift according to nest-level to ensure nested boxes don't collide \@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthHere}% % extract y-coordinate of previously stored south \tikz[overlay,remember picture]{% \pgfextracty{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}{center}}% \pgfextracty{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxSouthHere}{center}}% \global\algpx@oldPos=\algpx@oldPos% \global\algpx@newPos=\algpx@newPos% }% \ifdimcomp{\algpx@oldPos}{>}{\algpx@newPos}{% % new y is less than old one, so set it \@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}% }{% \@tikzmarkNow{algpx@codeBoxSouthDummy}% set something to keep in sync }% }{% \@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}% }% \FSPop{algpx@codeBoxStack}% \stepcounter{algpx@nestedCBoxCount}% }% % restore stack from tmp \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% \FSPop{algpx@codeBoxStackTmp}% }% } % set algpx@codeBoxWestMax of current box and all ancestors; argument is amount to shift left from current position \newcommand{\algpx@setCodeBoxWest}[1][0pt]{% \setcounter{algpx@nestedCBoxCount}{0}% \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp \@ifnodedefined{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}{% % get current position; shift according to nest-level to ensure nested boxes don't collide \@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestHere}% % extract x-coordinate of previously stored west \tikz[overlay,remember picture]{% \pgfextractx{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}{center}}% \pgfextractx{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxWestHere}{center}}% \global\algpx@oldPos=\algpx@oldPos% \global\algpx@newPos=\algpx@newPos% }% \ifdimcomp{\algpx@oldPos}{>}{\algpx@newPos}{% % new x is smaller than old one, so set it \@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}% }{% \@tikzmarkNow{algpx@codeBoxWestDummy}% set something to keep in sync }% }{% \@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}% }% \FSPop{algpx@codeBoxStack}% \stepcounter{algpx@nestedCBoxCount}% }% % restore stack from tmp \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% \FSPop{algpx@codeBoxStackTmp}% }% } % set algpx@codeBoxEastMax of current box and all ancestors \newcommand{\algpx@setCodeBoxEast}{% \setcounter{algpx@nestedCBoxCount}{0}% \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{% \FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp \@ifnodedefined{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}{% % get current position; shift according to nest-level to ensure nested boxes don't collide \@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastHere}% % extract x-coordinate of previously stored east \tikz[overlay,remember picture]{% \pgfextractx{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}{center}}% \pgfextractx{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxEastHere}{center}}% \global\algpx@oldPos=\algpx@oldPos% \global\algpx@newPos=\algpx@newPos% }% \ifdimcomp{\algpx@oldPos}{<}{\algpx@newPos}{% % new x is greater than old one, so set it \@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}% }{% \@tikzmarkNow{algpx@codeBoxEastDummy}% set something to keep in sync }% }{% \@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}% }% \FSPop{algpx@codeBoxStack}% \stepcounter{algpx@nestedCBoxCount}% }% % restore stack from tmp \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{% \FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}% \FSPop{algpx@codeBoxStackTmp}% }% } \newcommand{\algpx@setBoxesToStoredMax}{% \tikz[overlay,remember picture]{% \tikzmark{algpx@codeBoxNorth-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack})}% \tikzmark{algpx@codeBoxSouth-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack})}% \tikzmark{algpx@codeBoxWest-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack})}% \tikzmark{algpx@codeBoxEast-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack})}% }% } % add some space above and below box; more if several boxes are nested % first argument: number of boxes above % second argument: height of content % third argument: number of boxes below % fourth argument: depth of content \newcommand{\algpx@addBoxSpacing}[4]{% \ifnumcomp{0}{<}{#1}{% \rule{0pt}{\dimexpr #2 + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep + (\algpx@codeBoxSep * (#1 - 1))\relax}% }{}% \ifnumcomp{0}{<}{#3}{% \rule[\dimexpr -#4 - \algpx@codeBoxInnerSep - \algpx@codeBoxOuterSep - (\algpx@codeBoxSep * (#3 - 1))\relax]{0pt}{\dimexpr #4 + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep + (\algpx@codeBoxSep * (#3 - 1))\relax}% }{}% } % must be followed by \State, \If, \For etc. \newcommand{\BeginBox}[1][defaultCodeBox]{% \FSUnshift{algpx@startNewCodeBoxQueue}{\thealgpx@codeBoxCount}% add to queue; processed by \algpx@startCodeCommand %globally set tikz style (https://tex.stackexchange.com/a/47918) \begingroup% \globaldefs=1\relax% \pgfqkeys{/tikz}{algpx@codeBoxStyle\thealgpx@codeBoxCount/.style={#1}}% \endgroup% \stepcounter{algpx@codeBoxCount}% } \newcommand{\EndBox}{% \ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{% \PackageError{algpseudocodex}{BeginBox must be followed by State, If, For, etc. Use BoxedString instead}{}% \FSClear{algpx@startNewCodeBoxQueue}% }{% \ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}{% \unskip% \ifbool{algpx@executeEndVarwidth}{% \par\xdef\algpx@pdtemp{\the\prevdepth}% see https://tex.stackexchange.com/a/34982 \end{varwidth}\setbox0=\lastbox\usebox0% \setbool{algpx@executeEndVarwidth}{false}% \setbool{algpx@adjustHeight}{true}% \setbool{algpx@restorePrevdepth}{true}% }{}% \ifbool{algpx@setNorth}{% \algpx@setCodeBoxNorth{\the\ht0}% set north here shifted by height of current line \setbool{algpx@setNorth}{false}% }{}% \algpx@setCodeBoxEast% \algpx@setCodeBoxSouth{\the\dp0}% set south here shifted by depth of current line %adjust stored prevdepth for ended boxes \ifnumcomp{0}{<}{\value{algpx@endedBoxesCount}}{% \edef\algpx@pdtemp{\dimexpr \algpx@pdtemp + \algpx@codeBoxSep \relax}% }{% \edef\algpx@pdtemp{\dimexpr \algpx@pdtemp + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep \relax}% }% \algpx@setBoxesToStoredMax% \FSPop{algpx@codeBoxStack}% \stepcounter{algpx@endedBoxesCount}% }{% \PackageError{algpseudocodex}{No box to end}{}% }% }% } \newcommand{\BoxedString}[2][defaultCodeBox]{% \ifnumcomp{\value{algpx@nestedBoxedStringCount}}{=}{0}{% \setcounter{algpx@nestedBoxedStringMaxCount}{0}% reset max count for new boxes }{}% \stepcounter{algpx@nestedBoxedStringCount}% \ifnumcomp{\value{algpx@nestedBoxedStringMaxCount}}{<}{\value{algpx@nestedBoxedStringCount}}{% \setcounter{algpx@nestedBoxedStringMaxCount}{\value{algpx@nestedBoxedStringCount}}% }{}% \algpx@drawCodeBox{#1}{algpx@codeBoxNorth-\thealgpx@codeBoxCount}{algpx@codeBoxWest-\thealgpx@codeBoxCount}{algpx@codeBoxEast-\thealgpx@codeBoxCount}{algpx@codeBoxSouth-\thealgpx@codeBoxCount}% \FSPush{algpx@codeBoxStack}{\thealgpx@codeBoxCount}% \stepcounter{algpx@codeBoxCount}% \algpx@setCodeBoxWest% \ifmmode% % This works in equation but not in align / displaystyle etc. gets lost \savebox{\algpx@boxedStringBox}{$\m@th#2$}% \usebox{\algpx@boxedStringBox}% \else% \savebox{\algpx@boxedStringBox}{#2}% \usebox{\algpx@boxedStringBox}% \fi% \algpx@setCodeBoxEast% \algpx@setCodeBoxNorth{\the\ht\algpx@boxedStringBox}% \algpx@setCodeBoxSouth{\the\dp\algpx@boxedStringBox}% \algpx@setBoxesToStoredMax% \FSPop{algpx@codeBoxStack}% \addtocounter{algpx@nestedBoxedStringCount}{-1}% BoxedString ends here \ifnumcomp{\value{algpx@nestedBoxedStringCount}}{=}{0}{% \algpx@addBoxSpacing{\value{algpx@nestedBoxedStringMaxCount}}{\the\ht\algpx@boxedStringBox}{\value{algpx@nestedBoxedStringMaxCount}}{\the\dp\algpx@boxedStringBox}% }{}% } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Macros for indentation lines % \newcounter{algpx@indentCount} \FSCreate{algpx@indentStack}{0} \newbool{algpx@indJustEnded} % true after end with noend \newcounter{algpx@justUsedIndentCount} \newlength{\algpx@indStartY} \newlength{\algpx@indEndY} \newlength{\algpx@indStartX} % x coordinate of indent line % start indented block \newcommand{\algpx@startIndent}{% \ifbool{algpx@indLine}{% \@tikzmarkNow{algpx@indentStart-\thealgpx@indentCount}% \FSPush{algpx@indentStack}{\thealgpx@indentCount}% \stepcounter{algpx@indentCount}% }{}% } % end of indented block; optional argument 1 means that only interrupted by else \newcommand{\algpx@endIndent}[1][0]{% \ifbool{algpx@indLine}{% \ifbool{algpx@noEnd}{% \setlength{\algpx@minIndDist}{1pt}% }{% \setlength{\algpx@minIndDist}{\dimexpr \baselineskip + 1ex \relax}% }% \@tikzmarkNow{algpx@indentEnd-\FSTop{algpx@indentStack}}% \tikz[overlay,remember picture]{% \pgfextractx{\algpx@indStartX}{\pgfpointanchor{algpx@indentStart-\FSTop{algpx@indentStack}}{center}}% \ifbool{algpx@indJustEnded}{% % use same coordinates as for previous end \pgfextracty{\algpx@indEndY}{\pgfpointanchor{algpx@indentEnd-\thealgpx@justUsedIndentCount}{center}}% \draw[algpxIndentLine] ($(algpx@indentStart-\FSTop{algpx@indentStack})+(0.12em,-0.8ex)$) -- ($(\algpx@indStartX,\algpx@indEndY)+(0.12em,0ex)$) -- +(0.5em,0);% }{% % only draw if at least one line between start and end \pgfextracty{\algpx@indStartY}{\pgfpointanchor{algpx@indentStart-\FSTop{algpx@indentStack}}{center}}% \pgfextracty{\algpx@indEndY}{\pgfpointanchor{algpx@indentEnd-\FSTop{algpx@indentStack}}{center}}% \ifdimcomp{\algpx@indStartY-\algpx@minIndDist}{>}{\algpx@indEndY}{% \ifboolexpr{bool{algpx@noEnd} and test{\ifstrequal{#1}{0}}}{% % x of end is at end of line, extract x of start and use that instead \pgfextractx{\algpx@indStartX}{\pgfpointanchor{algpx@indentStart-\FSTop{algpx@indentStack}}{center}}% % draw additional line to right if noend and line is not interrupted \draw[algpxIndentLine] ($(algpx@indentStart-\FSTop{algpx@indentStack})+(0.12em,-0.8ex)$) -- ($(\algpx@indStartX,\algpx@indEndY)+(0.12em,0ex)$) -- +(0.5em,0);% }{% \draw[algpxIndentLine] ($(algpx@indentStart-\FSTop{algpx@indentStack})+(0.12em,-0.8ex)$) -- ($(algpx@indentEnd-\FSTop{algpx@indentStack})+(0.12em,2.0ex)$);% }% }{}% }% }% \ifboolexpr{not bool{algpx@indJustEnded} and bool{algpx@noEnd} and test{\ifstrequal{#1}{0}}}{% \setbool{algpx@indJustEnded}{true}% \setcounter{algpx@justUsedIndentCount}{\FSTop{algpx@indentStack}}% }{}% \FSPop{algpx@indentStack}% \ifstrequal{#1}{1}{% \algpx@startIndent% start new line if only interrupted }{}% }{}% } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Keywords % \algnewcommand\algorithmicend{\textbf{end}} \algnewcommand\algorithmicdo{\textbf{do}} \algnewcommand\algorithmicwhile{\textbf{while}} \algnewcommand\algorithmicfor{\textbf{for}} \algnewcommand\algorithmicforall{\textbf{for all}} \algnewcommand\algorithmicloop{\textbf{loop}} \algnewcommand\algorithmicrepeat{\textbf{repeat}} \algnewcommand\algorithmicuntil{\textbf{until}} \algnewcommand\algorithmicprocedure{\textbf{procedure}} \algnewcommand\algorithmicfunction{\textbf{function}} \algnewcommand\algorithmicif{\textbf{if}} \algnewcommand\algorithmicthen{\textbf{then}} \algnewcommand\algorithmicelse{\textbf{else}} \algnewcommand\algorithmicrequire{\textbf{Require:}} \algnewcommand\algorithmicensure{\textbf{Ensure:}} \algnewcommand\algorithmicreturn{\textbf{return}} \algnewcommand\algorithmicoutput{\textbf{output}} \algnewcommand\textproc{\textsc} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Loops % \algdef{SE}[WHILE]{While}{EndWhile}[1]{% \algpx@startIndent\algpx@startCodeCommand\algorithmicwhile\ #1\ \algorithmicdo% }{% \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicwhile% } \algdef{SE}[FOR]{For}{EndFor}[1]{% \algpx@startIndent\algpx@startCodeCommand\algorithmicfor\ #1\ \algorithmicdo% }{% \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicfor% } \algdef{S}[FOR]{ForAll}[1]{% \algpx@startIndent\algpx@startCodeCommand\algorithmicforall\ #1\ \algorithmicdo% } \algdef{SE}[LOOP]{Loop}{EndLoop}{% \algpx@startIndent\algpx@startCodeCommand\algorithmicloop% }{% \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicloop% } \algdef{SE}[REPEAT]{Repeat}{Until}{% \algpx@startIndent\algpx@startCodeCommand\algorithmicrepeat% }[1]{% \algpx@endIndent\algpx@setCodeBoxWest\algorithmicuntil\ #1% } \algdef{SE}[IF]{If}{EndIf}[1]{% \algpx@startIndent\algpx@startCodeCommand\algorithmicif\ #1\ \algorithmicthen% }{% \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicif% } \algdef{C}[IF]{IF}{ElsIf}[1]{% \algpx@endIndent[1]\algpx@startCodeCommand\algorithmicelse\ \algorithmicif\ #1\ \algorithmicthen% } \algdef{Ce}[ELSE]{IF}{Else}{EndIf}{% \algpx@endIndent[1]\algpx@startCodeCommand\algorithmicelse% } \algdef{SE}[PROCEDURE]{Procedure}{EndProcedure}[2]{% \algpx@startIndent\algpx@startCodeCommand\algorithmicprocedure\ \textproc{#1}\ifstrempty{#2}{}{(#2)}% }{% \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicprocedure% } \algdef{SE}[FUNCTION]{Function}{EndFunction}[2]{% \algpx@startIndent\algpx@startCodeCommand\algorithmicfunction\ \textproc{#1}\ifstrempty{#2}{}{(#2)}% }{% \algpx@endIndent\algpx@setCodeBoxWest\algorithmicend\ \algorithmicfunction% } \ifbool{algpx@noEnd}{% \algtext*{EndWhile}% \algtext*{EndFor}% \algtext*{EndLoop}% \algtext*{EndIf}% \algtext*{EndProcedure}% \algtext*{EndFunction}% % \pretocmd{\EndWhile}{\algpx@endIndent}{}{}% \pretocmd{\EndFor}{\algpx@endIndent}{}{}% \pretocmd{\EndLoop}{\algpx@endIndent}{}{}% \pretocmd{\EndIf}{\algpx@endIndent}{}{}% \pretocmd{\EndProcedure}{\algpx@endIndent}{}{}% \pretocmd{\EndFunction}{\algpx@endIndent}{}{}% }{}% \apptocmd{\State}{\algpx@startCodeCommand}{}{} \pretocmd{\State}{\algpx@endCodeCommand}{}{} \pretocmd{\While}{\algpx@endCodeCommand}{}{} \pretocmd{\EndWhile}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} \pretocmd{\For}{\algpx@endCodeCommand}{}{} \pretocmd{\EndFor}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} \pretocmd{\ForAll}{\algpx@endCodeCommand}{}{} \pretocmd{\Loop}{\algpx@endCodeCommand}{}{} \pretocmd{\EndLoop}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} \pretocmd{\Repeat}{\algpx@endCodeCommand}{}{} \pretocmd{\Until}{\algpx@endCodeCommand}{}{} \pretocmd{\If}{\algpx@endCodeCommand}{}{} \pretocmd{\ElsIf}{\algpx@endCodeCommand}{}{} \pretocmd{\Else}{\algpx@endCodeCommand}{}{} \pretocmd{\EndIf}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} \pretocmd{\Procedure}{\algpx@endCodeCommand}{}{} \pretocmd{\EndProcedure}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} \pretocmd{\Function}{\algpx@endCodeCommand}{}{} \pretocmd{\EndFunction}{\algpx@endCodeCommand[\ifbool{algpx@noEnd}{1}{0}]}{}{} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Other declarations % % dirty hack: execute drawing in argument of item and rest of \algpx@startCodeCommand outside % argument: text in item[.] \newcommand{\algpx@drawInItem}[1]{% \item[% \whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{% \FSPush{algpx@codeBoxStack}{\FSTop{algpx@startNewCodeBoxQueue}}% \algpx@drawCodeBox{algpx@codeBoxStyle\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxNorth-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxWest-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxEast-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxSouth-\FSTop{algpx@startNewCodeBoxQueue}}% \FSPop{algpx@startNewCodeBoxQueue}% \stepcounter{algpx@startedBoxesCount}% }% #1% ]% \setbool{algpx@indJustEnded}{false}% \setcounter{algpx@startedBoxesCount}{0}% \setcounter{algpx@endedBoxesCount}{0}% \setcounter{algpx@nestedBoxedStringMaxCount}{0}% \settowidth{\algpx@tmpLen}{#1}% \algpx@setCodeBoxWest[\dimexpr \labelsep + \algpx@tmpLen \relax]% \setbool{algpx@firstLine}{false}% \setbool{algpx@executeEndVarwidth}{true}% \begin{varwidth}[t]{\dimexpr \linewidth - \labelsep - \algpx@tmpLen + \leftmargin \relax}% \settoheight{\algpx@tmpLen}{#1}% \rule{0pt}{\algpx@tmpLen}% } \algnewcommand\Require{% \algpx@endCodeCommand% \ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{\setbool{algpx@setNorth}{true}}{}% \ifbool{algpx@firstLine}{% }{% \medskip% }% \algpx@drawInItem{\algorithmicrequire}% } \algnewcommand\Ensure{% \algpx@endCodeCommand% \ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{\setbool{algpx@setNorth}{true}}{}% \algpx@drawInItem{\algorithmicensure}% } \algnewcommand\Return{\algorithmicreturn{} } \algnewcommand\Output{\algorithmicoutput{} } \algnewcommand\Call[2]{\textproc{#1}\ifstrempty{#2}{}{(#2)}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Execute at beginning and end of algorithmic environment \AtBeginEnvironment{algorithmic}{% \setbool{algpx@firstLine}{true}% \setbool{algpx@setNorth}{false}% \setbool{algpx@executeEndVarwidth}{false}% \setbool{algpx@adjustHeight}{false}% \setbool{algpx@restorePrevdepth}{false}% \setcounter{algpx@startedBoxesCount}{0}% \setcounter{algpx@endedBoxesCount}{0}% } \AtEndEnvironment{algorithmic}{% \algpx@endCodeCommand% % Error checking \ifboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}} or test {\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{% \PackageError{algpseudocodex}{Some boxes have not ended}{}% }{}% } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Patch varwidth to allow \hfill \newif\if@useMaxWidth \AtBeginEnvironment{varwidth}{% \@useMaxWidthfalse% \renewcommand{\hfill}{\global\@useMaxWidthtrue\hspace{\fill}}% } % only set width to measured width if hfill was not used \patchcmd{\endvarwidth}{\ifdim\@vwid@<\hsize\hsize\@vwid@\fi}% {\ifdim\@vwid@<\hsize\if@useMaxWidth\else\hsize\@vwid@\fi\fi}% {}{\PackageWarning{algpseudocodex}{Failed to patch varwidth. \hfill probably does not work inside algorithmic.}} \algrenewcommand{\algorithmiccomment}[1]{{\color{gray}// #1}}