% \iffalse meta-comment
% vim: tw=80
%
%% File: algobox.dtx (C) Copyright 2016-2019 RIVAUD Julien
%%
%% It may be distributed and/or modified under the conditions of the
%% General Public License (GPL), either version 3 of this
%% license or (at your option) any later version.
%
%<*driver|package>
% The version of expl3 required is tested as early as possible, as
% some really old versions do not define \ProvidesExplPackage.
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\RequirePackage{expl3}[2018/06/19]
\def\ExplFileName{algobox}
\def\ExplFileDescription{Typeset Algobox programs}
\def\ExplFileDate{2019/09/29}
\def\ExplFileVersion{1.3}
%</driver|package>
%<*driver>
\documentclass[full,a4paper]{l3doc}
\usepackage{fontspec}
\usepackage{algobox}
\usepackage{url}
\begin{document}
  \def\Algobox{\textsc{AlgoBox}}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \textsf{\ExplFileName} package\\ \ExplFileDescription^^A
%   \thanks{This file describes v\ExplFileVersion,
%     last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
%  Julien ``\_FrnchFrgg\_'' \textsc{Rivaud}\thanks
%    {^^A
%      E-mail:
%        \href{mailto:frnchfrgg@free.fr}
%             {frnchfrgg@free.fr}^^A
%    }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
% \section{Documentation}
%
% \subsection{Getting support}
%
% If you find bugs or keywords not recognized by the package, you can report it
% at the address \url{https://gitlab.com/frnchfrgg-latex/algobox/issues}.
%
% \subsection{Rationale}
%
% French mathematics and/or computer science teachers can use \Algobox\
% (\url{http://www.xm1math.net/algobox/}) to teach algorithmics to beginners.
% It uses tree-like indentation, fixed-form structures entered by buttons and
% dialogs rather than free text. This prevents most typos or small beginner
% mistakes that are often hard to detect.
%
% \Algobox\ can save a project in its own format, and export in a variety of
% formats, including \LaTeX. Several problems arise:
% \begin{itemize}
%   \item The output is not similar to what \Algobox\ displays itself.
%   \item The generated code is standalone and uses dependencies that might not
%       be wanted, like \textsf{algorithm} and \textsf{algpseudocode} that can
%       clash with other algorithm-like packages.
%   \item The algorithm part of the generated code does not look like \Algobox\
%       code and can thus be annoying to modify by hand if needed.
% \end{itemize}
%
% This small package intends to solve the problem by using a syntax very close
% to the real \Algobox\ syntax and having a typeset output of the best quality
% possible, resembling the most to what \Algobox\ displays in its editing
% window.
%
% \subsection{Simple usage}
%
% To convert an \Algobox\ program to input suitable for this package you just
% have to:
%
% \begin{enumerate}
%   \item Copy the program from the \string"Tester l'algorithme\string"
%       window and remove the line numbers.
%   \item Add \cs{;} at the end of each line (or at the beginning of each line
%       if like me you prefer to have those out of the way). The reason is that
%       some constructs in \Algobox\ programs depend on the line cuts whereas
%       \TeX\ treats those as normal spaces by default. Of course, one can setup
%       \TeX\ so that it temporarily obeys lines, but it \emph{cannot work} if
%       the algorithm is between braces (if you put in in a macro like
%       \cs{fbox}).
%   \item Add a backslash at the beginning of all \Algobox\ keywords, like
%      "VARIABLES", "SI", "DEBUT_SINON" and so on.
%   \item Remove all underscores in \Algobox\ keywords. You probably want to
%       remove them in all cases because \Algobox\ programs are not typeset in
%       math mode and \TeX\ will complain that you tried to use a subscript. If
%       you really want an underscore, replace it by \cs{_} \emph{but not in
%       keywords} or they will not be recognized anymore.
%   \item Put everything between "\begin{algobox}" and
%       "\end{algobox}".
% \end{enumerate}
%
% Here is an example of the result:
%
% \begin{verbatim}
% \begin{algobox}
% \;    \VARIABLES
% \;      a1 \ESTDUTYPE NOMBRE
% \;      b1 \ESTDUTYPE NOMBRE
% \;      a2 \ESTDUTYPE NOMBRE
% \;      b2 \ESTDUTYPE NOMBRE
% \;    \DEBUTALGORITHME
% \;      \LIRE a1
% \;      \LIRE b1
% \;      \LIRE a2
% \;      \LIRE b2
% \;    \SI (a1 == a2) \ALORS
% \;      \DEBUTSI
% \;      \SI (b1 == b2) \ALORS
% \;        \DEBUTSI
% \;        \AFFICHER "Les droites sont parallèles"
% \;        \FINSI
% \;        \SINON
% \;          \DEBUTSINON
% \;          \AFFICHER "Les droites sont sécantes"
% \;          \FINSINON
% \;      \FINSI
% \;      \SINON
% \;        \DEBUTSINON
% \;        \AFFICHER "Les droites sont confondues"
% \;        \FINSINON
% \;  \FINALGORITHME
% \end{algobox}
% \end{verbatim}
%
% The spacing is only for your convenience as \TeX\ treats any number of
% consecutive spaces as a single one.
%
% Typesetting the previous example gives:
%
% \begin{algobox}
% \def"{\string"}
% \;    \VARIABLES
% \;      a1 \ESTDUTYPE NOMBRE
% \;      b1 \ESTDUTYPE NOMBRE
% \;      a2 \ESTDUTYPE NOMBRE
% \;      b2 \ESTDUTYPE NOMBRE
% \;    \DEBUTALGORITHME
% \;      \LIRE a1
% \;      \LIRE b1
% \;      \LIRE a2
% \;      \LIRE b2
% \;    \SI (a1 == a2) \ALORS
% \;      \DEBUTSI
% \;      \SI (b1 == b2) \ALORS
% \;        \DEBUTSI
% \;        \AFFICHER "Les droites sont parallèles"
% \;        \FINSI
% \;        \SINON
% \;          \DEBUTSINON
% \;          \AFFICHER "Les droites sont sécantes"
% \;          \FINSINON
% \;      \FINSI
% \;      \SINON
% \;        \DEBUTSINON
% \;        \AFFICHER "Les droites sont confondues"
% \;        \FINSINON
% \;  \FINALGORITHME
% \end{algobox}
%
% The algorithm is typeset as a TikZ picture, so is not breakable between pages.
%
% You can of course put the environment in anything you deem fit, like a "\fbox"
% for instance. Here is an example:
%
% \fbox{
% \begin{algobox}
% \def"{\string"}
% \;  \VARIABLES
% \;      note \ESTDUTYPE NOMBRE
% \;  \DEBUTALGORITHME
% \;      \LIRE note
% \;      \SI (note<10) \ALORS
% \;          \DEBUTSI
% \;          \AFFICHER "Il y a encore du travail"
% \;          \FINSI
% \;      \AFFICHER "On ne se relâche pas"
% \;      \POUR j \ALLANTDE 1 \A 25
% \;          \DEBUTPOUR
% \;          \AFFICHERCALCUL i+3
% \;          \FINPOUR
% \;  \FINALGORITHME
% \end{algobox}
% }
%
% \subsection{Customizing the appearance}
%
% TODO
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{\ExplFileName} implementation}
%
%    \begin{macrocode}
%<*package>
%<@@=algobox>
%    \end{macrocode}
%
%    \begin{macrocode}
\ProvidesExplPackage
  {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
%    \end{macrocode}
%    \begin{macrocode}
\RequirePackage{xparse}
\RequirePackage{environ}
\RequirePackage{tikz}

\ExplSyntaxOff
\usetikzlibrary{calc}
\ExplSyntaxOn

\RequirePackage{xcolor}

\int_new:N \l_@@_level_int

%    \end{macrocode}
% The colors are defined in "algohighlighter.cpp" in the \Algobox\ source,
% except for the tree lines color. The names here are the same, with "algobox"
% prepended.
%    \begin{macrocode}

\definecolor{algoboxarbre}{RGB}{146,146,146}
\definecolor{algoboxColorStandard}{HTML}{000000}
\definecolor{algoboxColorComment}{HTML}{606060}
\definecolor{algoboxColorBloc}{HTML}{800000}
\definecolor{algoboxColorCommande}{HTML}{0000CC}
\definecolor{algoboxColorSi}{HTML}{800080}
\definecolor{algoboxColorTantQue}{HTML}{DD6F06}
\definecolor{algoboxColorPour}{HTML}{BB8800}
\definecolor{algoboxColorFonction}{HTML}{9A4D00}

\tikzset{
    every~algobox/.style=,
    every~smalgobox/.style={baseline=(block.base)},
    algobox~ligne/.style={
        xshift=1em, text~depth=0pt,
        inner~xsep=0.1ex, inner~ysep=0.5ex
    },
    algobox~arbre/.style={ultra~thick, color=algoboxarbre},
    algobox~indentsymb/.style={x=1ex, y=0.6ex, color=algoboxarbre},
    algobox~indent/.style={xshift=2em},
    algobox~normal/.style={
        font=\sffamily,
        color=algoboxColorStandard,
    },
    algobox~commentaire/.style={
        algobox~normal/.try,
        color=algoboxColorComment,
    },
    algobox~commande/.style={
        algobox~normal/.try,
        color=algoboxColorCommande,
    },
    algobox~structure/.style={
        font=\sffamily\bfseries,
        color=algoboxColorBloc
    },
    algobox~sialors/.style={
        algobox~structure/.try,
        color=algoboxColorSi,
    },
    algobox~pour/.style={
        algobox~structure/.try,
        color=algoboxColorPour,
    },
    algobox~tantque/.style={
        algobox~structure/.try,
        color=algoboxColorTantQue,
    },
    algobox~fonctions/.style={
        algobox~structure/.try,
        color=algoboxColorFonction,
    },
}

%    \end{macrocode}
% \subsection{Formatting commands}
%    \begin{macrocode}


\tl_new:N \l_@@_lastnode_tl
\cs_new_protected:Nn \@@_block:nn {
    \node[algobox~ligne/.try,
        \tl_if_empty:nF{#1}{algobox~#1/.try},
        anchor=north~west
    ]
        (block) at (A\int_use:N \l_@@_level_int |- H)
        {\vphantom{A}#2};
    \draw[algobox~arbre/.try]
        (A\int_use:N \l_@@_level_int)
        -- (A\int_use:N \l_@@_level_int |- block.west)
                coordinate (A\int_use:N \l_@@_level_int)
        -- (block.west);
    \coordinate (H) at (block.south);
    \tl_set:Nn \l_@@_lastnode_tl {block}
}

\cs_new_protected:Nn \@@_indent:nn {
    \node[algobox~ligne/.try,
        \tl_if_empty:nF{#1}{algobox~#1/.try},
        anchor=north~west
    ]
        (block) at (A\int_use:N \l_@@_level_int |- H)
        {\vphantom{A}#2};
    \draw[algobox~arbre/.try]
        (A\int_use:N \l_@@_level_int)
        -- (A\int_use:N \l_@@_level_int |- H);
    \fill[algobox~indentsymb/.try]
        (A\int_use:N \l_@@_level_int |- block.west)
        +(0,-1) -- +(1,1) -- +(-1,1) -- cycle;
    \coordinate (H) at (block.south);
    \coordinate (T) at (A\int_use:N \l_@@_level_int |- H);
    \coordinate (A\int_use:N \l_@@_level_int) at (T);
    \int_incr:N \l_@@_level_int
    \coordinate[algobox~indent/.try] (A\int_use:N \l_@@_level_int) at (T);
    \tl_set:Nn \l_@@_lastnode_tl {block}
}
\cs_new_protected:Nn \@@_unindent: {
    \int_decr:N \l_@@_level_int
}

\cs_new_protected:Nn \@@_node:nn {
    \node[algobox~#1/.try, anchor=base~west, inner~xsep=0pt]
        (node) at (\l_@@_lastnode_tl.base~east) {#2};
    \tl_set:Nn \l_@@_lastnode_tl {node}
}

%    \end{macrocode}
% \subsection{Parsing helpers}
%    \begin{macrocode}


\cs_new_protected:Nn \@@_parseall:n {
    \tl_set:Nn \l_tmpa_tl {#1}
    \seq_set_split:NnV \l_tmpa_seq {\;} \l_tmpa_tl
    % Now build up the algorithm body, working around the few infix notations.
    \tl_clear:N \l_@@_body_tl
    \seq_map_variable:NNn \l_tmpa_seq \l_tmpa_tl {
        \tl_if_in:NnT \l_tmpa_tl {\ESTDUTYPE} {
            \tl_put_left:Nn \l_tmpa_tl {\@@_ESTDUTYPE:w}
        }
        \tl_if_in:NnT \l_tmpa_tl {\PRENDLAVALEUR} {
            \tl_put_left:Nn \l_tmpa_tl {\@@_PRENDLAVALEUR:w}
        }
        \tl_put_right:Nn \l_tmpa_tl { \; }
        \tl_put_right:NV \l_@@_body_tl \l_tmpa_tl
    }
    \tl_use:N \l_@@_body_tl
}

\bool_new:N \l_@@_balanced_first_bool
\cs_new_protected:Npn \@@_new_balanced_command:nNNnn #1#2#3 {
    \cs_new_protected:cpn {#1} ##1 #2 {
        \tl_set:Nn \l_@@_prefix_tl { ##1 }
        \tl_clear:N \l_@@_balanced_tl
        \bool_set_true:N \l_@@_balanced_first_bool
        \use:c {#1_stage2} #2
    }
    \cs_new_protected:cpn {#1_stage2} ##1 #2 ##2 #3 {
        \tl_put_right:Nn \l_@@_balanced_tl { ##1 }
        \bool_if:NF \l_@@_balanced_first_bool {
            \tl_put_right:Nn \l_@@_balanced_tl { #2 }
        }
        \tl_if_in:nnTF {##2} {#2} {
            \bool_set_false:N \l_@@_balanced_first_bool
            \use:c {#1_stage2} ##2 \q_mark
        }{
            \tl_put_right:Nn \l_@@_balanced_tl { ##2 }
            \tl_replace_all:Nnn \l_@@_balanced_tl {\q_mark} {#3}
            \tl_set:Nx \l_tmpa_tl {
                \exp_not:c {#1_stage3}
                \exp_not:V \l_@@_prefix_tl
                \exp_not:n {#2}
                {
                    \exp_not:V \l_@@_balanced_tl
                }
            }
            \tl_use:N \l_tmpa_tl
        }
    }
    \exp_args:Nc \NewDocumentCommand {#1_stage3}
}

\cs_new_protected:Npn \@@_if_next:NTF #1#2#3 {
    \peek_meaning_remove_ignore_spaces:NTF \; {
        \@@_if_next:NTF #1 {#2} {#3}
    }{
        \peek_meaning_remove_ignore_spaces:NTF \par {
            \@@_if_next:NTF #1 {#2} {#3}
        }{
            \peek_meaning_ignore_spaces:NTF #1 {#2} {#3}
        }
    }
}
%    \end{macrocode}
% \subsection{Parsing/typesetting commands}
%    \begin{macrocode}

\NewDocumentCommand \@@_ESTDUTYPE:w { +u{\ESTDUTYPE} +u{\;} } {
    \@@_block:nn {normal} {
        \ignorespaces #1 \unskip\c_space_token\null
    }
    \@@_node:nn {commande}{EST_DU_TYPE}
    \@@_node:nn {normal}{\null\c_space_token#2}
}

\NewDocumentCommand \@@_FINALGORITHME:w {} {
    \int_while_do:nNnn \l_@@_level_int > \c_zero_int {
        \@@_unindent:
    }
    \@@_block:nn {structure} {FIN_ALGORITHME}
}

\NewDocumentCommand \@@_PRENDLAVALEUR:w { u{\PRENDLAVALEUR} m } {
    \@@_block:nn {normal} {
        \ignorespaces#1\unskip\c_space_token\null
    }
    \@@_node:nn {commande}{PREND_LA_VALEUR}
    \@@_node:nn {normal}{\null\c_space_token#2}
}

\@@_new_balanced_command:nNNnn
            {@@_SI:w} \DEBUTSI \FINSI { r() u{\DEBUTSI} +m }
{
    \@@_indent:nn {sialors} {SI}
    \@@_node:nn {normal}{\null\c_space_token(#1)\c_space_token\null}
    \@@_node:nn {sialors}{ALORS}
    \@@_block:nn {sialors} {DEBUT_SI}
    #3
    \@@_block:nn {sialors} {FIN_SI}
    \@@_if_next:NTF \SINON {
        \@@_SINON:w
    }{
        \@@_unindent:
    }
}
\@@_new_balanced_command:nNNnn
            {@@_SINON:w} \DEBUTSINON \FINSINON { u{\DEBUTSINON} +m } {
    \@@_indent:nn {sialors} {SINON}
    \@@_block:nn {sialors} {DEBUT_SINON}
    #2
    \@@_block:nn {sialors} {FIN_SINON}
    \@@_unindent:
    \@@_unindent:
}

\@@_new_balanced_command:nNNnn
            {@@_POUR:w} \DEBUTPOUR \FINPOUR
            { u{\ALLANTDE} u{\A} u{\DEBUTPOUR} +m } {
    \@@_indent:nn {pour} {POUR}
    \@@_node:nn {normal}{\null\c_space_token #1\unskip\c_space_token\null}
    \@@_node:nn {pour}{ALLANT_DE}
    \@@_node:nn {normal}{\null\c_space_token #2\unskip
                        \c_space_token A~#3\unskip\c_space_token\null}
    \@@_block:nn {pour} {DEBUT_POUR}
    #4
    \@@_block:nn {pour} {FIN_POUR}
    \@@_unindent:
}

\@@_new_balanced_command:nNNnn {@@_TANTQUE:w} \DEBUTTANTQUE \FINTANTQUE
        { r() u{\DEBUTTANTQUE} +m }
{
    \@@_indent:nn {tantque} {TANT_QUE}
    \@@_node:nn {normal}{\null\c_space_token(#1)\c_space_token\null}
    \@@_node:nn {tantque}{FAIRE}
    \@@_block:nn {tantque} {DEBUT_TANT_QUE}
    #3
    \@@_block:nn {tantque} {FIN_TANT_QUE}
    \@@_unindent:
}

\NewDocumentCommand \@@_FONCTION:w { +u{\;} } {
    \int_while_do:nNnn \l_@@_level_int > \c_one_int {
        \@@_unindent:
    }
    \@@_indent:nn {fonctions} {FONCTION}
    \@@_node:nn {normal}{\null\c_space_token#1}
}

\NewDocumentCommand \@@_LINE:w { s O{normal} m } {
    \IfBooleanTF {#1} {
        \@@_indent:nn {#2} {#3}
        \@@_unindent:
    }{
        \@@_block:nn {#2} {#3}
    }
}

\NewDocumentCommand \@@_NODE:w { O{normal} m } {
    \@@_node:nn {#1} {#2}
}

%    \end{macrocode}
% \subsection{User commands and environment}
%    \begin{macrocode}

\cs_new_protected_nopar:Nn \@@_make_keyword:n {
    \tl_set:Nn \l_tmpa_tl {#1}
    \tl_replace_all:Nnn \l_tmpa_tl {_} {}
    \cs_set:cpn {\l_tmpa_tl} {\@@_keyword:nw {#1}}
}

\NewDocumentCommand \@@_keyword:nw {m +u{\;}} {
    \@@_block:nn {commande} {#1}
    \@@_node:nn {normal}{\null\c_space_token#2}
}

\cs_new_protected_nopar:Nn \@@_make_structure:nn {
    \tl_set:Nn \l_tmpa_tl {#2}
    \tl_replace_all:Nnn \l_tmpa_tl {_} {}
    \cs_set:cpn {\l_tmpa_tl} {\@@_topstructure:nn {#1}{#2}}
}

\cs_new_protected_nopar:Nn \@@_topstructure:nn {
    \int_while_do:nNnn \l_@@_level_int > \c_zero_int {
        \@@_unindent:
    }
    \@@_indent:nn {#1} {#2}
}

\cs_new_protected_nopar:Nn \@@_make_func_structure:nn {
    \tl_set:Nn \l_tmpa_tl {#1}
    \tl_replace_all:Nnn \l_tmpa_tl {_} {}
    \cs_set:cpn {\l_tmpa_tl} {\@@_funcstructure:nn {#1}{#2}}
}

\cs_new_protected_nopar:Nn \@@_funcstructure:nn {
    \int_while_do:nNnn \l_@@_level_int > { 2 } {
        \@@_unindent:
    }
    \bool_if:nTF {#2}{\@@_indent:nn}{\@@_block:nn} {fonctions} {#1}
}

\clist_const:Nn \c_@@_keywords_clist {
    PAUSE, LIRE, AFFICHERCALCUL, AFFICHER,
    TRACER_POINT, TRACER_POINT_Rouge, TRACER_POINT_Vert,
    TRACER_POINT_Bleu, TRACER_POINT_Blanc,
    TRACER_SEGMENT, TRACER_SEGMENT_Rouge, TRACER_SEGMENT_Vert,
    TRACER_SEGMENT_Bleu, TRACER_SEGMENT_Blanc,
    RENVOYER, APPELER_FONCTION
}

\cs_new_protected_nopar:Nn \@@_begincode:n {
    \int_zero:N \l_@@_level_int
    \begin{tikzpicture}[#1]
        \coordinate (H) at (0,0);
        \coordinate (A\int_use:N \l_@@_level_int) at (0,0);
        \cs_set_eq:NN \par \prg_do_nothing:
        \cs_set_eq:NN \; \prg_do_nothing:
        \cs_set_eq:NN \LINE             \@@_LINE:w
        \cs_set_eq:NN \NODE             \@@_NODE:w
        \cs_set_eq:NN \FINALGORITHME    \@@_FINALGORITHME:w
        \cs_set_eq:NN \SI               \@@_SI:w
        \cs_set_eq:NN \POUR             \@@_POUR:w
        \cs_set_eq:NN \TANTQUE          \@@_TANTQUE:w
        \cs_set_eq:NN \FONCTION         \@@_FONCTION:w
        \cs_set:Npn \//##1\;            {\@@_block:nn{commentaire}{//##1}}
        \clist_map_function:NN \c_@@_keywords_clist \@@_make_keyword:n
        \@@_make_structure:nn {structure} {VARIABLES}
        \@@_make_structure:nn {structure} {DEBUT_ALGORITHME}
        \@@_make_structure:nn {fonctions} {FONCTIONS_UTILISEES}
        \@@_make_func_structure:nn {VARIABLES_FONCTION} \c_true_bool
        \@@_make_func_structure:nn {DEBUT_FONCTION} \c_false_bool
        \@@_make_func_structure:nn {FIN_FONCTION} \c_false_bool
}
\cs_new_protected_nopar:Nn \@@_closecode: {
    \end{tikzpicture}
}



\NewDocumentCommand \smalgobox { O{} m } {
    \group_begin:
    \@@_begincode:n {every~smalgobox/.try,#1}
    \@@_parseall:n {#2}
    \@@_closecode:
    \group_end:
}

\NewDocumentEnvironment {algobox} {O{}} {
    \cs_set_protected:Nn \@@_algobox:n {
        \@@_begincode:n {every~algobox/.try,#1}
        \@@_parseall:n {##1}
        \@@_closecode:
    }
    \Collect@Body\@@_algobox:n
}{
}
%</package>
%    \end{macrocode}
%
% \end{implementation}
