%! Package: algxpar %! Author: Jander Moreira %! Email = moreira.jander@gmail.com %! suppress = FileNotFound \NeedsTeXFormat{LaTeX2e}[2005/12/01] \ProvidesPackage{algxpar}[2024/10/23 v0.99.2 Algorithms with multi-line/paragraph support and some enhancements] %% Documentation \NewDocumentCommand{\AlgVersion}{}{0.99.2} \NewDocumentCommand{\AlgDate}{}{2024/10/23} %% Required packages \RequirePackage{algorithmicx} \RequirePackage{algpseudocode} \RequirePackage{ragged2e} \RequirePackage{xcolor} \RequirePackage{fancyvrb} % to load verbatim preserving tabs \RequirePackage{pgfopts} \RequirePackage{amssymb} \RequirePackage{pgfmath} \RequirePackage{varwidth} % \RequirePackage{ifthen} \RequirePackage{tikz} \usetikzlibrary{calc, arrows} \RequirePackage{etoolbox} % \RequirePackage{listings} % to load verbatim with tabs % \RequirePackage{tcolorbox} % to save verbatim %%% Internal commands \ExplSyntaxOn % set_keyword:nnn creates or update a keyword in a language % #1: language (e.g., brazilian) % #2: keyword (e.g. while) % #3: value (e.g, enquanto) \cs_new:Npn \set_keyword:nnn #1#2#3 { \tl_clear_new:c { g_keyword_#1_#2_tl } \tl_set:cn { g_keyword_#1_#2_tl } { #3 } } % get_keyword:nn returs a keyword in a language % #1: language (e.g., brazilian) % #2: keyword (e.g. while) % returns: keyword text (e.g. enquanto) \cs_new:Npn \get_keyword:nn #1#2 { \cs_if_exist_use:cTF { g_keyword_#1_#2_tl } { } { \cs_if_exist_use:cTF { g_keyword_english_#2_tl } { } { \msg_new:nnn { algxpar } { keyword-not-found } { Keyword~'#2'~not~found. } \msg_fatal:nn { algxpar } { keyword-not-found } } } } %%% User commands % SetKeyword: create or update a keyword in a language % #1: language (e.g., brazilian) % #2: keyword (e.g. while) % #3: value (e.g, enquanto) \NewDocumentCommand{\SetKeyword}{ O{\axp@Language} m m }{ \set_keyword:nnn { #1 } { #2 } { #3 } } % Keyword: returns a formatted keyword in the current language % #1: keyword (e.g. while) \NewDocumentCommand{\Keyword} { O{\axp@Language} m }{ \mbox{\textcolor{\axp@KeywordColor}{\axp@KeywordFont\get_keyword:nn{#1}{#2}}} } % Constant: returns a formatted constant in the current language % #1: keyword (e.g. True) \NewDocumentCommand{\Constant} { m }{ \mbox{\textcolor{\axp@ConstantColor}{\axp@ConstantFont\get_keyword:nn{\axp@Language}{#1}}} } % Module: returns a formatted name for a procedure ou function % #1: name \NewDocumentCommand{\Module} { m }{ \mbox{\textcolor{\axp@ModuleColor}{\axp@ModuleFont#1}} } % CommentSymbol: returns the formatted comment symbol \NewDocumentCommand{\CommentSymbol} { }{ \mbox{\textcolor{\axp@CommentColor}{\axp@CommentFont\axp@CommentSymbol}} } % CommentSymbol: returns the formatted comment symbol right \NewDocumentCommand{\CommentSymbolRight} { }{ \mbox{\textcolor{\axp@CommentColor}{\axp@CommentFont\axp@CommentSymbolRight}} } % axp@RenewFullyExpandedDocumentCommand: fully expands argument before % renewing document command % #1: macro % #2: value \NewDocumentCommand{\axp@RenewFullyExpandedDocumentCommand} { m m }{ \exp_args:NNnV \RenewDocumentCommand #1 { } { #2 } } \ExplSyntaxOff %% Settings \newif\ifaxp@NoEnd\axp@NoEndfalse % whether line with 'end' is used or not \newif\ifaxp@IsStatement\axp@IsStatementfalse % set in \Statep \newif\ifaxp@ShowBoxes\axp@ShowBoxesfalse % show parboxes for debugging \newif\ifaxp@LineBalanceAuto % true for 'auto'; false for 'fixed' \newif\ifaxp@IndentLines\axp@IndentLinesfalse % draw lines in blocks \NewDocumentCommand{\axp@DisableEnds}{}{% \axp@NoEndtrue% \RenewDocumentCommand{\ALG@noend}{}{t}% \algtext*{EndWhile}% \algtext*{EndFor}% \algtext*{EndLoop}% \algtext*{EndIf}% \algtext*{EndProcedure}% \algtext*{EndFunction}% \algtext*{EndSwitch}% \algtext*{EndCase}% \algtext*{EndOtherwise}% } \NewDocumentCommand{\axp@EnableEnds}{}{% \axp@NoEndfalse% \RenewDocumentCommand{\ALG@noend}{}{f}% \algrenewtext{EndWhile}{\Keyword{endwhile}}% \algrenewtext{EndFor}{\Keyword{endfor}}% \algrenewtext{EndLoop}{\Keyword{endloop}}% \algrenewtext{EndIf}{\Keyword{endif}}% \algrenewtext{EndProcedure}{\Keyword{endprocedure}}% \algrenewtext{EndFunction}{\Keyword{endfunction}}% \algrenewtext{EndSwitch}{\Keyword{endswitch}}% \algrenewtext{EndCase}{\Keyword{endcase}}% \algrenewtext{EndOtherwise}{\Keyword{endotherwise}}% } \axp@EnableEnds % update end-line texts %% General options \pgfkeys{ /algxpar/options/.cd, % language language/.store in = \axp@Language, % styles text font/.store in = \axp@TextFont, text color/.store in = \axp@TextColor, text style/.store in = \axp@TextStyle, comment font/.store in = \axp@CommentFont, comment color/.store in = \axp@CommentColor, comment style/.store in = \axp@CommentStyle, keyword font/.store in = \axp@KeywordFont, keyword color/.store in = \axp@KeywordColor, constant font/.store in = \axp@ConstantFont, constant color/.store in = \axp@ConstantColor, module font/.store in = \axp@ModuleFont, module color/.store in = \axp@ModuleColor, % comment symbol/.store in = \axp@CommentSymbol, comment symbol right/.store in = \axp@CommentSymbolRight, comment separator width/.store in = \axp@CommentSeparatorWidth, % noend/.code = {\axp@DisableEnds}, no end/.code = {\axp@DisableEnds}, end/.code = {\axp@EnableEnds}, % % keywords/.code = {\pgfkeysalso{/algxpar/languages/.cd, \trim@spaces{#1}}}, keywords/.code = {\axp@LanguageSet{#1}}, % algorithmic indent/.store in = \algorithmicindent, statement indent/.store in = \axp@StatementIndent, parameter indent/.store in = \axp@ParameterIndent, % indent lines/.is if = axp@IndentLines, line style/.code = {\tikzset{line style/.style = {#1}}}, % show boxes/.is if = axp@ShowBoxes, % comment width/.code = {% \axp@LineBalanceAutotrue% \ifthenelse{\equal{auto}{#1}}{% \axp@LineBalanceAutotrue% }{% \axp@LineBalanceAutofalse% \ifthenelse{\equal{nice}{#1}}{% \DeclareDocumentCommand{\axp@CommentFixedWidth}{}{0.4\linewidth}% }{% \DeclareDocumentCommand{\axp@CommentFixedWidth}{}{#1}% }% }% }, % % style/.style = {\pgfkeysalso{/algxpar/styles/#}}, } \NewDocumentCommand{\AlgSet}{ > { \TrimSpaces } m }{% \pgfkeys{% /algxpar/options/.cd, /utils/exec = \pgfkeysalsofrom{#1}, }% } % %% Styles % \NewDocumentCommand{\AlgStyle}{ > { \TrimSpaces } m > { \TrimSpaces m }{% % \pgfkeys{ % /algxpar/style/.cd, % #1/.style = {#2} % } % } %% Languages and translations \pgfkeys{ /algxpar/languages/.cd, .unknown/.code = {\SetKeyword{\pgfkeyscurrentname}{#1}} } \NewDocumentCommand{\AlgLanguageSet}{ > { \TrimSpaces } m > { \TrimSpaces } m }{% \AlgSet{language = #1}% \pgfkeys{ /algxpar/languages/.cd, #2 }% } \NewDocumentCommand{\axp@LanguageSet}{ > { \TrimSpaces } m }{% \pgfkeys{ /algxpar/languages/.cd, #1 } } \input{algxpar-english.kw} % always loads default language % general settings defaults \AlgSet{ language = english, text font = , text color = ., text style = \RaggedRight, comment font = \slshape, comment color = .!70, comment style = \RaggedRight, keyword font = \bfseries, keyword color = ., constant font = \scshape, constant color = ., module font = \scshape, module color = ., comment symbol = $\triangleright$, comment symbol right = $\triangleleft$, comment separator width = 1em, algorithmic indent = 1.5em, statement indent = 1em, parameter indent = 0pt, indent lines = false, line style = {lightgray, thick}, show boxes = false, comment width = auto, } %% Package options \pgfkeys{ /algxpar/.cd, language/.store in = \axp@Language, noend/.is if = axp@NoEnd, .unknown/.code = { \axp@RenewFullyExpandedDocumentCommand{\axp@Language}{\pgfkeyscurrentname} \input{algxpar-\pgfkeyscurrentname.kw} } } \pgfkeys{ /algxpar/.cd, language = english, noend = false, } \ProcessPgfOptions{/algxpar} \ifaxp@NoEnd\axp@DisableEnds\fi% globally disable 'ends' % axp@SetToWidth: \settowidth allowing multi-line text % #1: existing length % #2: text \NewDocumentCommand{\axp@SetToWidth}{ m m }{% \settowidth{#1}{% \begin{varwidth}{500cm}% 5 meters = infinity #2 \end{varwidth}% }% } % axp@DefineCommand: defines command structure % #1: keyword (e.g, while) % #2: block text (e.g. a > 0) % #3: complement keyword (e.g. do) % #4: comment text % #5: options \NewDocumentCommand{\axp@DefineCommand}{ m m m m m }{% \DeclareDocumentCommand{\axp@CommandKeyword}{}{#1}% \DeclareDocumentCommand{\axp@CommandText}{}{#2}% \DeclareDocumentCommand{\axp@CommandComplementKeyword}{}{#3}% \DeclareDocumentCommand{\axp@CommentText}{}{#4}% \def\axp@CommandOptions{#5}% def: to be accepeted in \pgfkeysalsofrom } % axp@MakeSingleToken: texto before and after only if token has some width % #1: text before toke % #2: token % #3: text after token \newlength{\axp@TokenWidth} \NewDocumentCommand{\axp@MakeSingleToken}{ m m m }{% \axp@SetToWidth{\axp@TokenWidth}{#2}% \ifdimcomp{\axp@TokenWidth}{>}{0pt}{#1}{}% #2% \ifdimcomp{\axp@TokenWidth}{>}{0pt}{#3}{}% } \newif\ifaxp@NoCommentPresent \newlength{\axp@TextWidth} \newlength{\axp@CommentWidth} %%%%%%%% LINES \NewDocumentCommand{\axp@MarkLineBegin}{}{% \ifbool{axp@IndentLines}{% \stepcounter{axp@BlockLevelCounter}% \tikz[remember picture] \coordinate (axp-block-start-\theaxp@BlockLevelCounter) (0, 0);% % \tikz[remember picture, overlay] \draw[<-] (axp-block-start-\theaxp@BlockLevelCounter) -- ++ (-4em, 0.5ex) node[anchor = east] {B:\theaxp@BlockLevelCounter};% }{}% }% \NewDocumentCommand{\axp@MarkLineEndShort}{}{% \ifbool{axp@IndentLines}{% \tikz[remember picture] \coordinate (axp-block-end-\theaxp@BlockLevelCounter) (0, 0);% \begin{tikzpicture}[remember picture, overlay] \draw[line style] ($ (axp-block-start-\theaxp@BlockLevelCounter) + (0.3ex, -1ex) $) -- ($ (axp-block-end-\theaxp@BlockLevelCounter) + (0.3ex, 1em) $); \end{tikzpicture}% \addtocounter{axp@BlockLevelCounter}{-1}% }% } \NewDocumentCommand{\axp@MarkLineEndCont}{}{% \ifbool{axp@IndentLines}{% \tikz[remember picture] \coordinate (axp-block-end-\theaxp@BlockLevelCounter) (0, 0);% \begin{tikzpicture}[remember picture, overlay] \draw[line style] ($ (axp-block-start-\theaxp@BlockLevelCounter) + (0.3ex, -1ex) $) -- ($ (axp-block-end-\theaxp@BlockLevelCounter) + (0.3ex, 1em) $); \end{tikzpicture}% \addtocounter{axp@BlockLevelCounter}{-1}% }% } \NewDocumentCommand{\axp@MarkLineEndFinal}{}{% \ifbool{axp@IndentLines}{% \tikz[remember picture] \coordinate (axp-block-end-\theaxp@BlockLevelCounter) (0, 0);% \begin{tikzpicture}[remember picture, overlay] \draw[line style] ($ (axp-block-start-\theaxp@BlockLevelCounter) + (0.3ex, -1ex) $) -- ($ (axp-block-end-\theaxp@BlockLevelCounter) + (0.3ex, 0) $) |- ++ (1ex, 0); \end{tikzpicture}% \addtocounter{axp@BlockLevelCounter}{-1}% }% } % % *********************************************** % % For debugging! \NewDocumentCommand{\msg}{ m O{-1} }{% \begin{tikzpicture}[overlay] \draw[black!30] (0, 0.1) -- (#2, 0.3) node[fill=black!5, anchor=east] {\scriptsize\color{darkgray}#1}; \end{tikzpicture}% } % axp@CalculateDimensions: evaluate space needed for text and comments % #1: nesting ajustment (1 when openning a block; 0 when closing) % #2: text % #3: comment % sets: % \axp@TextWidth % \axp@CommentWidth, when needed \newlength{\axp@FullTextWidth} \newlength{\axp@FullCommentWidth} \newlength{\axp@CommentSymbolWidth} \newlength{\axp@CurrentLineWidth} \newlength{\axp@RemainingWidth} \NewDocumentCommand{\axp@CalculateDimensions}{ m m m }{% \booltrue{axp@NoCommentPresent}% \axp@SetToWidth{\axp@FullTextWidth}{\axp@TextFont#2}% text \axp@SetToWidth{\axp@FullCommentWidth}{\axp@CommentFont#3}% comment \ifdimcomp{\axp@FullCommentWidth}{=}{0pt}{% % No comments present % \msg{no comment!}% \global\booltrue{axp@NoCommentPresent}% % \ifbool{axp@LineBalanceAuto}{% \setlength{\axp@TextWidth}{ \dimexpr \linewidth - \axp@CurrentTokenWidth - (\algorithmicindent)*(\theALG@nested - #1) }% \ifdimcomp{\axp@FullTextWidth}{<}{\axp@TextWidth}{% \axp@TextWidth\axp@FullTextWidth% makes the parbox fit the actual text width }{}% % }{} }{% % Yep, we have a comment in this line % \msg{got a comment!}% \global\boolfalse{axp@NoCommentPresent}% \axp@SetToWidth{\axp@CommentSymbolWidth}{\hspace{\axp@CommentSeparatorWidth}\CommentSymbol~}% \deflength{\axp@CurrentLineWidth}{ \linewidth - \axp@CurrentTokenWidth - (\algorithmicindent)*(\theALG@nested - #1) }% \ifbool{axp@LineBalanceAuto}{% % 'auto': decide here how to balance text and comment widths \setlength{\axp@RemainingWidth}{ \dimexpr \axp@CurrentLineWidth - \axp@FullTextWidth - \axp@FullCommentWidth - \axp@CommentSymbolWidth }% \null% I don't understand the difference this null makes here! % \msg{\the\axp@RemainingWidth}% \ifdimcomp{\axp@RemainingWidth}{>}{0pt}{% % Both text and comment fit the line \axp@TextWidth\axp@FullTextWidth% \axp@CommentWidth\axp@FullCommentWidth% % \msg{fits \the\axp@RemainingWidth}% }{% % Text/comment will go multi-line % \msg{not fit \the\axp@RemainingWidth}% \pgfmathsetmacro{\axp@CurrentRatio}{ int(round(\axp@FullTextWidth/(\axp@FullTextWidth + \axp@FullCommentWidth) * 100)) }% \ifnumcomp{\axp@CurrentRatio}{<}{25}{% never less than 0.25 \edef\axp@CurrentRatio{25}% }{% \ifnumcomp{\axp@CurrentRatio}{>}{75}{% never more than 0.75 \edef\axp@CurrentRatio{75}% }{}% }% \pgfmathparse{ (100 - \axp@CurrentRatio)/100 * \axp@CurrentLineWidth - \axp@CommentSymbolWidth }% \setlength{\axp@CommentWidth}{\pgfmathresult pt}% \pgfmathparse{\axp@CurrentLineWidth - \axp@CommentWidth - \axp@CommentSymbolWidth}% \setlength{\axp@TextWidth}{\pgfmathresult pt}% % fine tunning the widths \axp@SetToWidth{\axp@CommentWidth}{% \begin{varwidth}[t]{\axp@CommentWidth}% \axp@CommentStyle% \textcolor{\axp@CommentColor}{\axp@CommentFont#3}\strut% \end{varwidth}% }% \pgfmathparse{\axp@CurrentLineWidth - \axp@CommentWidth - \axp@CommentSymbolWidth}% \setlength{\axp@TextWidth}{\pgfmathresult pt}% % \msg{\the\axp@TextWidth}% }% }{% % 'fixed': limit comment width % todo: think about using \axp@CurrentLineWidth instead of \linewidth \setlength{\axp@CommentWidth}{\axp@CommentFixedWidth}% \setlength{\axp@TextWidth}{ \dimexpr \axp@CurrentLineWidth - \axp@CommentWidth - \axp@CommentSymbolWidth }% }% \setlength{\axp@RemainingWidth}{ \dimexpr \linewidth - \axp@CurrentTokenWidth - (\algorithmicindent)*(\theALG@nested - #1) - \axp@CommentWidth - \axp@CommentSymbolWidth }% }% } \newcounter{cont} \newif\ifaxp@CloseBlock % axp@MakeCommand: builds the command (see axp@DefineCommand) % #1 (star): star = end block; no star = begin block \NewDocumentCommand{\axp@MakeCommand}{ s }{% \IfBooleanTF{#1}{% \axp@MarkLineEndShort% }{% \ifaxp@CloseBlock% \axp@MarkLineEndCont% \axp@CloseBlockfalse% \fi% \axp@MarkLineBegin% }% \axp@DoCommand{% ajustment for opening/closing blocks \IfBooleanTF{#1}{0}{1}% }{% command or module+name \axp@MakeSingleToken{}{\axp@CommandKeyword}{\ifaxp@IsModule(\else\ \fi}% }{% text or module arguments \axp@CommandText\ifaxp@IsModule)\fi% }{% command complement \axp@MakeSingleToken{ }{\axp@CommandComplementKeyword}{}% }{% comment \axp@CommentText% }{% options \axp@CommandOptions% }% } %! formatter = off \newsavebox{\axp@SaveBox} \NewDocumentEnvironment{axp@FBox}{}{% \begin{lrbox}{\axp@SaveBox}% }{% \end{lrbox}% \ifaxp@ShowBoxes% \begingroup% \setlength{\fboxrule}{0.001pt}% \setlength{\fboxsep}{0pt}% \color{.!20}\fbox{\color{.}\usebox{\axp@SaveBox}}% \endgroup% \else% \usebox{\axp@SaveBox}% \fi% } % axp@DoCommand: builds the command (see axp@DefineCommand) % #1: 1 when openning block; 0 when closing % #2: command % #3: text % #4: command complement % #5: comment % #6: options \newlength{\axp@CurrentTokenWidth} \NewDocumentCommand{\axp@DoCommand}{ m m m m m m }{% \AlgSet{#6}% % Dimensions \axp@SetToWidth{\axp@CurrentTokenWidth}{#2}% \axp@CalculateDimensions{#1}{{\axp@TextStyle\axp@TextFont#3}#4}{#5}% % % Making the line: body #2% \begin{axp@FBox}% \ifbool{axp@IsModule}{\hspace{\axp@ParameterIndent}}{}% \parbox[t]{\axp@TextWidth}{% \ifaxp@IsStatement% \setlength{\hangindent}{\axp@StatementIndent}% \fi% \axp@TextStyle% \textcolor{\axp@TextColor}{\axp@TextFont{#3}}#4\strut% }% \end{axp@FBox}% % Making the line: comment \ifbool{axp@NoCommentPresent}{}{% \hspace{\axp@CommentSeparatorWidth}\hfill\CommentSymbol~% \begin{axp@FBox}% \ifbool{axp@LineBalanceAuto}{% \begin{varwidth}[t]{\axp@CommentWidth}% \axp@CommentStyle% \textcolor{\axp@CommentColor}{\axp@CommentFont#5}\strut% \end{varwidth}% }{% \parbox[t]{\axp@CommentWidth}{% \axp@CommentStyle% \textcolor{\axp@CommentColor}{\axp@CommentFont#5}\strut% }% }% \end{axp@FBox}% }% } %% Keyword quick references \NewDocumentCommand{\To}{}{\axp@MakeSingleToken{}{\Keyword{to}}{ }} \NewDocumentCommand{\DownTo}{}{\axp@MakeSingleToken{}{\Keyword{downto}}{ }} \NewDocumentCommand{\Step}{}{\axp@MakeSingleToken{}{\Keyword{step}}{ }} \NewDocumentCommand{\Continue}{}{\Keyword{continue}} \NewDocumentCommand{\Break}{}{\Keyword{break}} \RenewDocumentCommand{\Return}{}{\axp@MakeSingleToken{}{\Keyword{return}}{ }} \NewDocumentCommand{\ByRef}{}{\Constant{byref}} \NewDocumentCommand{\ByValue}{}{\Constant{byvalue}} \NewDocumentCommand{\True}{}{\Constant{true}} \NewDocumentCommand{\False}{}{\Constant{false}} \NewDocumentCommand{\Nil}{}{\Constant{nil}} \newcommand{\Id}[1]{\ensuremath{\emph{\rmfamily#1}}} % \newcommand{\TextString}[1]{\textrm{\normalfont``{\ttfamily\mbox{#1}}''}} % \algnewcommand{\VisibleSpace}{\textrm{\color{black!70}\textvisiblespace}} %% Headings \NewDocumentCommand{\Description}{}{\item[\Keyword{description}:]} \NewDocumentCommand{\Input}{}{\item[\Keyword{input}:]} \NewDocumentCommand{\Output}{}{\item[\Keyword{output}:]} \RenewDocumentCommand{\Ensure}{}{\item[\Keyword{ensure}:]} \RenewDocumentCommand{\Require}{}{\item[\Keyword{require}:]} % Read, write \NewDocumentCommand{\Set}{ m m }{% \PackageWarning{alxpar}{The macro \string\Set\ is no longer supported.}% \Id{#1} \gets #2% } \NewDocumentCommand{\Read}{}{\Keyword{read} } \NewDocumentCommand{\Write}{}{\Keyword{write} } % %% Comments \algnewcommand{\CommentIn}[1]{% \begin{axp@FBox} \textcolor{\axp@CommentColor}{\CommentSymbol~\axp@CommentFont#1~\CommentSymbolRight}% \end{axp@FBox}% } \NewDocumentCommand{\Commentl}{ m D<>{} }{% \begingroup% \AlgSet{#2}% \textcolor{\axp@CommentColor}{\CommentSymbol~\axp@CommentFont#1\strut}% \endgroup% } \RenewDocumentCommand{\Comment}{ m D<>{} }{% \hfill\Commentl{#1}<#2>% } \newlength{\axp@CurrentIndent} \newcounter{axp@BlockCounter} \newcounter{axp@BlockLevelCounter} \NewDocumentCommand{\axp@BeginGroup}{}{% \begingroup% } \NewDocumentCommand{\axp@EndGroup}{}{% \global\edef\axp@SaveIndent{\the\ALG@tlm}% \endgroup% \setlength{\ALG@tlm}{\axp@SaveIndent}% } %% Statep: statement % #1: old style comment % #2: text % #3: comments % #4: options \NewDocumentCommand{\Statep}{ O{} +m O{} D<>{} }{% \axp@IsStatementtrue% \State\axp@DoCommand{1}{}{#2}{}{#1#3}{#4}% \axp@IsStatementfalse% } \RenewDocumentCommand{\Statex}{}{% \item[]\strut% } %% While \algblockdefx[While]{While}{EndWhile}{\axp@MakeCommand}{\axp@MakeCommand*} % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\While}{ O{} m O{} D<>{} }{% \axp@BeginGroup% \axp@DefineCommand{\Keyword{while}}{#2}{\Keyword{do}}{#1#3}{#4}% \ALG@makeentity{While}% } % #1: comment % #2: options \RenewDocumentCommand{\EndWhile}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endwhile}}{}{}{#1}{#2}% \ALG@makeentity{EndWhile}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup% } %% Repeat \algblockdefx[Repeat]{Repeat}{Until}{\axp@MakeCommand}{\axp@MakeCommand*} % #1: comments % #2: options \RenewDocumentCommand{\Repeat}{ O{} D<>{} }{% \axp@BeginGroup% \axp@DefineCommand{\Keyword{repeat}}{}{}{#1}{#2}% \ALG@makeentity{Repeat}% } % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\Until}{ O{} m O{} D<>{} }{% \axp@DefineCommand{\Keyword{until}}{#2}{}{#1#3}{#4}% \ALG@makeentity{Until}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup% } %% Loop \algblockdefx[Loop]{Loop}{EndLoop}{\axp@MakeCommand}{\axp@MakeCommand*} % #1: comment % #2: options \RenewDocumentCommand{\Loop}{ O{} D<>{} }{% \axp@BeginGroup% \axp@DefineCommand{\Keyword{loop}}{}{}{#1}{#2}% \ALG@makeentity{Loop}% } % #1: comment % #2: options \RenewDocumentCommand{\EndLoop}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endloop}}{}{}{#1}{#2}% \ALG@makeentity{EndLoop}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup% } %% If \algblockdefx[If]{If}{EndIf}{\axp@MakeCommand}{\axp@MakeCommand*} % + else if \algcblockdefx[If]{If}{ElsIf}{EndIf}{\axp@MakeCommand}{\axp@MakeCommand*} % + else \algcblockdefx[If]{If}{Else}{EndIf}[1][]{\axp@MakeCommand}{\axp@MakeCommand*} % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\If}{ O{} m O{} D<>{} }{% \axp@BeginGroup% \axp@DefineCommand{\Keyword{if}}{#2}{\Keyword{then}}{#1#3}{#4}% \ALG@makeentity{If}% } % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\ElsIf}{ O{} m O{} D<>{} }{% \axp@DefineCommand{\Keyword{else}~\Keyword{if}}{#2}{\Keyword{then}}{#1#3}{#4}% \axp@CloseBlocktrue% \ALG@makeentity{ElsIf}% } % #1: comment % #2: options \RenewDocumentCommand{\Else}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{else}}{}{}{#1}{#2}% \axp@CloseBlocktrue% \ALG@makeentity{Else}% } % #1: comment % #2: options \RenewDocumentCommand{\EndIf}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endif}}{}{}{#1}{#2}% \ALG@makeentity{EndIf}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup% } %% Switch \algblockdefx[Switch]{Switch}{EndSwitch}{\axp@MakeCommand}{\axp@MakeCommand*} % + case \algblockdefx[Case]{Case}{EndCase}{\axp@MakeCommand}{\axp@MakeCommand*} % + otherwise \algblockdefx[Otherwise]{Otherwise}{EndOtherwise}{\axp@MakeCommand}{\axp@MakeCommand*} % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\Switch}{ O{} m O{} D<>{} }{% \axp@BeginGroup \axp@DefineCommand{\Keyword{switch}}{#2}{}{#1#3}{#4}% \ALG@makeentity{Switch}% } % #1: comment % #2: options \RenewDocumentCommand{\EndSwitch}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endswitch}}{}{}{#1}{#2}% \ALG@makeentity{EndSwitch}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup } % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\Case}{ O{} m O{} D<>{} }{% \axp@BeginGroup \axp@DefineCommand{\Keyword{case}}{#2}{\Keyword{do}}{#1#3}{#4}% \ALG@makeentity{Case}% } % #1: comment % #2: options \RenewDocumentCommand{\EndCase}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endcase}}{}{}{#1}{#2}% \ALG@makeentity{EndCase}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup } % #1: comment % #2: options \RenewDocumentCommand{\Otherwise}{ O{} D<>{} }{% \axp@BeginGroup \axp@DefineCommand{\Keyword{otherwise}}{}{}{#1}{#2}% \ALG@makeentity{Otherwise}% } % #1: comment % #2: options \RenewDocumentCommand{\EndOtherwise}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endotherwise}}{}{}{#1}{#2}% \ALG@makeentity{EndOtherwise}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup } % \newcommand{\Range}[3][]{% % \ensuremath{% % #2% % \def\temp{#1}% % \mathcal{\ldotp\ldotp}#3 % \ifx\temp\empty\relax\else{\ensuremath{\mathcal{:}#1}}\fi% % }% % } %% For, for each, for all \algblockdefx[For]{For}{EndFor}{\axp@MakeCommand}{\axp@MakeCommand*} \algblockdefx[For]{ForEach}{EndFor}{\axp@MakeCommand}{\axp@MakeCommand*} \algblockdefx[For]{ForAll}{EndFor}{\axp@MakeCommand}{\axp@MakeCommand*} % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\For}{ O{} m O{} D<>{} }{% \axp@BeginGroup \axp@DefineCommand{\Keyword{for}}{#2}{\Keyword{do}}{#1#3}{#4}% \ALG@makeentity{For}% } % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\ForEach}{ O{} m O{} D<>{} }{% \axp@BeginGroup \axp@DefineCommand{\Keyword{foreach}}{#2}{\Keyword{do}}{#1#3}{#4}% \ALG@makeentity{ForEach}% } % #1: old style comment % #2: text % #3: comment % #4: options \RenewDocumentCommand{\ForAll}{ O{} m O{} D<>{} }{% \axp@BeginGroup \axp@DefineCommand{\Keyword{forall}}{#2}{\Keyword{do}}{#1#3}{#4}% \ALG@makeentity{For}% } % #1: comment % #2: options \RenewDocumentCommand{\EndFor}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endfor}}{}{}{#1}{#2}% \ALG@makeentity{EndFor}% \ifaxp@NoEnd\axp@MarkLineEndFinal\fi% \axp@EndGroup } %% Procedure, function, calls \newif\ifaxp@IsModule \algblockdefx[Procedure]{Procedure}{EndProcedure}{\axp@MakeCommand}{\axp@MakeCommand*} % #1: old style comment % #2: name % #3: arguments % #4: comment % #5: options \RenewDocumentCommand{\Procedure}{ O{} m m O{} D<>{} }{% \axp@BeginGroup \axp@IsModuletrue% \axp@DefineCommand{\Keyword{procedure}~\Module{#2}}{#3}{}{#1#4}{#5}% \ALG@makeentity{Procedure}% \axp@IsModulefalse% } % #1: comment % #2: options \RenewDocumentCommand{\EndProcedure}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endprocedure}}{}{}{#1}{#2}% \axp@MarkLineEndFinal% \ALG@makeentity{EndProcedure}% \axp@EndGroup } \algblockdefx[Function]{Function}{EndFunction}{\axp@MakeCommand}{\axp@MakeCommand*} % #1: old style comment % #2: name % #3: arguments % #4: comment % #5: options \RenewDocumentCommand{\Function}{ O{} m m O{} D<>{} }{% \axp@BeginGroup \axp@IsModuletrue% \axp@DefineCommand{\Keyword{function}~\Module{#2}}{#3}{}{#1#4}{#5}% \ALG@makeentity{Function}% \axp@IsModulefalse% } % #1: comment % #2: options \RenewDocumentCommand{\EndFunction}{ O{} D<>{} }{% \axp@DefineCommand{\Keyword{endfunction}}{}{}{#1}{#2}% \axp@MarkLineEndFinal% \ALG@makeentity{EndFunction}% \axp@EndGroup } \RenewDocumentCommand{\Call}{ m m D<>{} }{% \begingroup% \AlgSet{#3}% \Module{#1}\textcolor{\axp@TextColor}{\axp@TextFont(#2)}% \endgroup% } %% NewLine \newcommand{\NewLine}{\\} % %% DefineCode, UseCode, \ShowCode % \newenvironment{DefineCode}[1] % {\begingroup\tcbverbatimwrite{\jobname_code_#1.tmp}} % {\endtcbverbatimwrite\endgroup} % \newcommand{\UseCode}[1]{\input{\jobname_code_#1.tmp}} % \newcommand{\ShowCode}[2][]{{\small\VerbatimInput[tabsize=4, #1]% % {\jobname_code_#2.tmp}}} % % \algrenewcommand{\alglinenumber}[1]{% % \hspace{-1.5em}\color{black!35}{\scriptsize#1}\raisebox{0.2ex}{\tiny$\blacktriangleright$}% % } % %% axp@algparbox %% Adding options to the 'algorithmic' environment \NewCommandCopy{\axp@AlgorithmicxAlgorithmic}{\algorithmic} \NewCommandCopy{\axp@AlgorithmicxEndAlgorithmic}{\endalgorithmic} \RenewDocumentCommand{\algorithmic}{ O{} D<>{} }{% \begingroup% \AlgSet{#2}% \axp@AlgorithmicxAlgorithmic[#1]% } \RenewDocumentCommand{\endalgorithmic}{}{% \axp@AlgorithmicxEndAlgorithmic% \endgroup% } \endinput