diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/algobox/algobox.dtx |
Initial commit
Diffstat (limited to 'macros/latex/contrib/algobox/algobox.dtx')
-rw-r--r-- | macros/latex/contrib/algobox/algobox.dtx | 612 |
1 files changed, 612 insertions, 0 deletions
diff --git a/macros/latex/contrib/algobox/algobox.dtx b/macros/latex/contrib/algobox/algobox.dtx new file mode 100644 index 0000000000..2e26eb79f4 --- /dev/null +++ b/macros/latex/contrib/algobox/algobox.dtx @@ -0,0 +1,612 @@ +% \iffalse meta-comment +% vim: tw=80 +% +%% File: algobox.dtx (C) Copyright 2016-2017 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}[2016/01/19] +\def\ExplFileName{algobox} +\def\ExplFileDescription{Typeset Algobox programs} +\def\ExplFileDate{2017/09/04} +\def\ExplFileVersion{1.2a} +%</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 { + \@@_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 { + \@@_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 { + \@@_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 > \c_two { + \@@_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} |