%! Package: algxpar
%! Author: Jander Moreira
%! Email =  moreira.jander@gmail.com

\NeedsTeXFormat{LaTeX2e}[2005/12/01]
\ProvidesPackage{algxpar}[2023/06/26 v0.99 Algorithms with multi-line/paragraph support and some enhancements]

%% Documentation
\NewDocumentCommand{\AlgVersion}{}{0.99}
\NewDocumentCommand{\AlgDate}{}{2023/06/26}


%% 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{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}}
}


% RenewFullyExpandedDocumentCommand: fully expands argument before
%   renewing document command
% #1: macro
% #2: value
\NewDocumentCommand{\RenewFullyExpandedDocumentCommand} { m m }{
    \exp_args:NNnV \RenewDocumentCommand #1 { } { #2 }
}

\ExplSyntaxOff

\NewDocumentCommand{\axp@DisableEnds}{}{%
    \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}{}{%
    \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

%% 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'

%% General options
%! formatter = off
\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,
    %
    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}%
            }%
        }%
    },
}
%! formatter = on

\NewDocumentCommand{\AlgSet}{ > { \TrimSpaces } m }{%
    \pgfkeys{%
        /algxpar/options/.cd,
        /utils/exec = \pgfkeysalsofrom{#1},
    }%
}


%% 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,
    show boxes = false,
    comment width = auto,
}


%% Package options
\pgfkeys{
    /algxpar/.cd,
    language/.store in = \axp@Language,
    noend/.is if = axp@NoEnd,
    .unknown/.code = {
        %! suppress = FileNotFound
        \input{algxpar-\pgfkeyscurrentname.kw}
        \RenewFullyExpandedDocumentCommand{\axp@Language}{\pgfkeyscurrentname}
    }
}
\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 }{%
    \settowidth{\axp@TokenWidth}{#2}%
    \ifdim\axp@TokenWidth>0pt\relax#1\fi%
    #2%
    \ifdim\axp@TokenWidth>0pt\relax#3\fi%
}

\newif\ifaxp@NoCommentPresent
\newlength{\axp@TextWidth}
\newlength{\axp@CommentWidth}


% 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 }{%
    \axp@SetToWidth{\axp@FullTextWidth}{\axp@TextFont#2}% text
    \axp@SetToWidth{\axp@FullCommentWidth}{\axp@CommentFont#3}% comment
    %! formatter = off
    \ifdim\axp@FullCommentWidth=0pt\relax%
        % No comments present
        \axp@NoCommentPresenttrue%
        \setlength{\axp@TextWidth}{
            \dimexpr \linewidth - \axp@CurrentTokenWidth - (\algorithmicindent)*(\theALG@nested - #1)
        }%
    \else
        % Yep, we have a comment
        \axp@NoCommentPresentfalse%
        \settowidth{\axp@CommentSymbolWidth}{\hspace{\axp@CommentSeparatorWidth}\CommentSymbol~}%
        \setlength{\axp@CurrentLineWidth}{
            \dimexpr \linewidth - \axp@CurrentTokenWidth - (\algorithmicindent)*(\theALG@nested - #1)
        }%
        \ifaxp@LineBalanceAuto%
            % 'auto': decide here how to balance text and comment widths
            \setlength{\axp@RemainingWidth}{
                \dimexpr \axp@CurrentLineWidth - \axp@FullTextWidth - \axp@FullCommentWidth - \axp@CommentSymbolWidth
            }%
            \ifdim\axp@RemainingWidth>0pt\relax%
                % Both text and comment fit the line
                \axp@TextWidth\axp@FullTextWidth%
                \axp@CommentWidth\axp@FullCommentWidth%
            \else%
                % Text/comment will go multi-line
                \pgfmathsetmacro{\axp@CurrentRatio}{
                    int(round(\axp@FullTextWidth/(\axp@FullTextWidth + \axp@FullCommentWidth) * 100))
                }%
                \ifnum\axp@CurrentRatio<25\relax%  never less than 0.25
                    \edef\axp@CurrentRatio{25}%
                \fi%
                \ifnum\axp@CurrentRatio>75\relax%  never more than 0.75
                    \edef\axp@CurrentRatio{75}%
                \fi%
                \pgfmathparse{
                    \axp@CurrentRatio/100 * \axp@CurrentLineWidth - \axp@CommentSymbolWidth/2
                }%
                \setlength{\axp@TextWidth}{\pgfmathresult pt}%
                \pgfmathparse{\axp@CurrentLineWidth - \axp@TextWidth - \axp@CommentSymbolWidth}%
                \setlength{\axp@CommentWidth}{\pgfmathresult pt}%
                % fine tunning the widths
                \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}%
            \fi%
        \else%
            % '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
            }%
        \fi%
        \setlength{\axp@RemainingWidth}{
            \dimexpr \linewidth - \axp@CurrentTokenWidth -
            (\algorithmicindent)*(\theALG@nested - #1) -
            \axp@CommentWidth - \axp@CommentSymbolWidth
        }%
    \fi%
    %
    \ifdim\axp@FullTextWidth<\axp@TextWidth\relax%
        \axp@TextWidth\axp@FullTextWidth%  makes the parbox fit the actual text width
    \fi%
    %! formatter = on
}

% axp@MakeCommand: builds the command (see axp@DefineCommand)
% #1 (star): star = end block; no star = begin block
\NewDocumentCommand{\axp@MakeCommand}{ s }{%
    \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%
}
%! formatter = on


% 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
    \settowidth{\axp@CurrentTokenWidth}{#2}%
    \axp@CalculateDimensions{#1}{{\axp@TextStyle\axp@TextFont#3}#4}{#5}%
    %
    % Making the line: body
    #2%
    %! formatter = off
    \begin{axp@FBox}%
    \ifaxp@IsModule\hspace{\axp@ParameterIndent}\fi%
        \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
    \ifaxp@NoCommentPresent\else%
        \hspace{\axp@CommentSeparatorWidth}\hfill\CommentSymbol~%
        \begin{axp@FBox}%
            \ifaxp@LineBalanceAuto
                \begin{varwidth}[t]{\axp@CommentWidth}%
                    \axp@CommentStyle%
                    \textcolor{\axp@CommentColor}{\axp@CommentFont#5}\strut%
                \end{varwidth}%
            \else
                \parbox[t]{\axp@CommentWidth}{%
                    \axp@CommentStyle%
                    \textcolor{\axp@CommentColor}{\axp@CommentFont{#5}}\strut%
                }%
            \fi%
        \end{axp@FBox}%
    \fi%
    %! formatter = on
}


%% 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{\True}{}{\Constant{true}}
\NewDocumentCommand{\False}{}{\Constant{false}}
\NewDocumentCommand{\Nil}{}{\Constant{nil}}

\newcommand{\Id}[1]{\ensuremath{\textit{\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}

\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}%
    \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}%
    \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}%
    \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}%
    \ALG@makeentity{ElsIf}%
}
% #1: comment
% #2: options
\RenewDocumentCommand{\Else}{ O{} D<>{} }{%
    \axp@DefineCommand{\Keyword{else}}{}{}{#1}{#2}%
    \ALG@makeentity{Else}%
}
% #1: comment
% #2: options
\RenewDocumentCommand{\EndIf}{ O{} D<>{} }{%
    \axp@DefineCommand{\Keyword{endif}}{}{}{#1}{#2}%
    \ALG@makeentity{EndIf}%
    \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}%
    \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}%
    \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}%
    \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}%
    \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}{}{#4}{#5}%
    \ALG@makeentity{Procedure}%
    \axp@IsModulefalse%
}
% #1: comment
% #2: options
\RenewDocumentCommand{\EndProcedure}{ O{} D<>{} }{%
    \axp@DefineCommand{\Keyword{endprocedure}}{}{}{#1}{#2}%
    \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}{}{#4}{#5}%
    \ALG@makeentity{Function}%
    \axp@IsModulefalse%
}
% #1: comment
% #2: options
\RenewDocumentCommand{\EndFunction}{ O{} D<>{} }{%
    \axp@DefineCommand{\Keyword{endfunction}}{}{}{#1}{#2}%
    \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