diff options
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/generic/simplekv/README | 4 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/simplekv/simplekv-fr.pdf | bin | 329306 -> 326887 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/generic/simplekv/simplekv-fr.tex | 161 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/simplekv/simplekv.sty | 1 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/simplekv/simplekv.tex | 374 |
5 files changed, 241 insertions, 299 deletions
diff --git a/Master/texmf-dist/doc/generic/simplekv/README b/Master/texmf-dist/doc/generic/simplekv/README index d612d38b6b7..1172bd96a6a 100644 --- a/Master/texmf-dist/doc/generic/simplekv/README +++ b/Master/texmf-dist/doc/generic/simplekv/README @@ -3,9 +3,9 @@ ___________________________________ L'extension simplekv - v0.1 + v0.2 - 8 aout 2017 + 27 avril 2020 ___________________________________ Authors : Christian Tellechea diff --git a/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.pdf b/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.pdf Binary files differindex 797171dd55e..950d64baa11 100644 --- a/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.pdf +++ b/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.pdf diff --git a/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.tex b/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.tex index c899feeb738..e23a0ae0782 100644 --- a/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.tex +++ b/Master/texmf-dist/doc/generic/simplekv/simplekv-fr.tex @@ -22,7 +22,7 @@ \let\do\@makeother \dospecials \ttfamily\small\@noligs \make@car@active\<{\begingroup$\langle$\itshape}% - \make@car@active\>{$\rangle$\endgroup}% + \make@car@active\>{\/$\rangle$\endgroup}% \obeylines\obeyspaces \def\code@ii##1#1{##1\par\medbreak\endgroup}% \code@ii @@ -126,25 +126,23 @@ \endgroup \vskip2cm \leftskip=.2\linewidth \rightskip=.2\linewidth \small - Cette petite extension est une implémentation d'un système dit à «clé/valeurs» pour \TeX{} ou \LaTeX. Aucune fioriture inutile n'a été codée, elle comporte juste l'essentiel. + Cette petite extension est une implémentation d'un système dit à «\<clés>/\<valeurs>» pour \TeX{} ou \LaTeX. Elle comporte juste l'essentiel, aucune fioriture inutile n'a été codée et aucune extension tierce n'est nécessaire à son fonctionnement. \end{titlepage} \section{Clés, valeurs} -Lorsqu'une macro doit recevoir des paramètres dont le nombre n'est pas fixe ou connu, il est commode de procéder par \<clés> et \<valeurs>. Beaucoup d'extensions allant en ce sens existent déjà. - -Le but de celle-ci n'est pas de grossir le nombre déjà trop grand de ces extensions, c'est simplement un morceau de l'extension \texttt{hlist} qui a été converti en extension car ce système \<clé>/\<valeurs> est également utilisé par l'extension \texttt{scratch}.\medskip - +Lorsqu'une macro doit recevoir des paramètres dont le nombre n'est pas fixe ou connu, il est commode de procéder par \<clés> et \<valeurs>. +\medskip Voici brièvement les définitions et les limitations des structures mises à disposition : \begin{itemize} - \item une \<clé> est un mot désignant un paramètre; il est formé de préférence avec des caractères de code de catégorie 11 (lettres), 12 (autres caractères sauf la virgule) et 10 (l'espace). On peut cependant y mettre des caractères ayant d'autres codes de catégorie, dans la limitation de ce qui est admis dans la primitive \verb|\detokenize|; + \item une \<clé> est un mot désignant un paramètre; il est formé de préférence avec des caractères de code de catégorie 11 (lettres), 12 (autres caractères sauf la virgule et le signe \verb|=|) et 10 (l'espace). On peut cependant y mettre des caractères ayant d'autres codes de catégorie, dans la limitation de ce qui est admis dans la primitive \verb|\detokenize|; une \<clé>, même si cela revêt peu de signification, peut être vide; \item la syntaxe pour assigner une \<valeur> à une \<clé> est : \hbox{\<clé>=\<valeur>}; \item les espaces qui précèdent et qui suivent la \<clé> et la \<valeur> sont ignorés, mais \emph{pas ceux} qui se trouvent à l'intérieur de la \<clé> ou de la \<valeur>; \item une \<valeur> est un \<code> arbitraire; \item si une \<valeur> est entourée d'accolades, ces dernières seront retirées : \verb|<clé>=<valeur>| est donc équivalent à \verb|<clé>={<valeur>}|; + \item lorsqu'une valeur est entourée de \emph{plusieurs} imbrications d'accolades, seul le niveau externe est retiré et donc \verb|<clé>={{<valeur>}}| est compris comme \verb|<clé>={<valeur>}|; \item lorsque plusieurs couples de \<clés>/\<valeurs> doivent être spécifiés, ils sont séparés les uns des autres par des virgules; \item une virgule ne peut figurer dans une \<valeur> que si la virgule est dans un niveau d'accolades; par exemple, \verb|foo=1,5| n'est pas valide car la \<valeur> s'étend jusqu'au 1. Il faudrait écrire \verb|foo={1,5}| pour spécifier une valeur de \verb|1,5|; - \item lorsqu'une valeur est entourée de \emph{plusieurs} d'accolades, seul le niveau externe est retiré; \item les \<valeurs> sont stockées \emph{telles qu'elles sont lues} ; en particulier, aucun développement n'est effectué; \item les définitions sont \emph{locales} : par conséquent, toute \<clé> définie ou modifiée dans un groupe est restaurée à son état antérieur à la sortie du groupe; \item des \<clé>/\<valeurs> destinées à une même macro ou à un même usage doivent être regroupées dans un ensemble dont on choisit le nom. Un tel ensemble est appelé \<trousseau>. @@ -152,87 +150,154 @@ Voici brièvement les définitions et les limitations des structures mises à dispo \section{Commandes mises à disposition} -\paragraph{La macro \texttt{\char`\\setKVdefault}} -Cette commande est un préalable à toute utilisation de \<clés> puisqu'elle définit un \<trousseau> contenant des \<clés> et leurs \<valeurs> par défaut. +\paragraph{Les macro \texttt{\char`\\setKV} et \texttt{\char`\\setKVdefault}} +Ces commandes définissent des \<clés> et leur assignent des \<valeurs> dans un \<trousseau>. La seule différence entre les deux macros est que \verb|\setKVdefault|, en plus d'assigner les \<valeurs> aux \<clés>, les sauvegarde en vue d'une restauration ultérieure avec \verb|\restoreKV|. On écrit -\begin{center} \verb|\setKVdefault[<trousseau>]{<clé 1>=<valeur 1>,<clé 2>=<valeur 2>,...,<clé i>=<valeur i>}| -\end{center} +\code|\setKV[<trousseau>]{<clé 1>=<valeur 1>,<clé 2>=<valeur 2>,...,<clé n>=<valeur n>}| Il faut noter que \begin{itemize} - \item l'argument entre accolades contenant les \<clés> et les \<valeurs> ne peut pas être vide; + \item l'argument entre accolades contenant les \<clés> et les \<valeurs> ne devrait pas être vide, sauf à vouloir définir une \<clé> booléenne vide égale à \texttt{true}; + \item lors de la lecture des \<clés>/\<valeurs>, la virgule et le signe égal ont leurs catcodes rendus égaux à 12; \item le nom du \<trousseau>, bien qu'entre crochet, est \emph{obligatoire}, mais il peut être vide bien que cela ne soit pas conseillé; - \item si plusieurs \<clés> sont identiques, seule la dernière \<valeur> sera prise en compte; - \item les \<valeurs> peuvent être booléennes, auquel cas, elles \emph{doivent} être «\texttt{true}» ou «\texttt{false}» en caractères de catcode 11; + \item si une même \<clé> figure plusieurs fois, la \<valeur> retenue sera celle de la dernière assignation; + \item les \<valeurs> peuvent être booléennes auquel cas, elles \emph{doivent} être «\texttt{true}» ou «\texttt{false}» en caractères de catcode 11; \item si une \<valeur> est omise, elle est comprise comme étant «\texttt{true}». Ainsi, écrire - \code|\setKVdefault[foo]{mon bool}| + \code|\setKV[foo]{mon bool}| est équivalent à - \code|\setKVdefault[foo]{mon bool = true}| - \item il est \emph{déconseillé} d'exécuter plusieurs fois \verb|\setKVdefault| pour le même \<trousseau>. Si cela est indispensable, il convient de redéfinir \emph{toutes} les \<clés> qui figuraient dans les précédents appels de \verb|\setKVdefault|. + \code|\setKV[foo]{mon bool = true}| \end{itemize} -\paragraph{La macro \texttt{\char`\\setKV}} -Cette macro fonctionne selon les mêmes principes et limitations que \verb|\setKVdefault|, sauf qu'elle redéfinit une ou plusieurs \<clés> dont les \<valeurs> ont précédemment été définies par \verb|\setKVdefault|. - -Si une \<clé> n'a pas été prédéfinie par \verb|\setKVdefault|, une erreur sera émise. - \paragraph{La macro \texttt{\char`\\useKV}} Cette macro purement développable renvoie la \<valeur> préalablement associée à une \<clé> dans un \<trousseau>: -\code|\useKV[<trousseau>]{<clé>}| + \code|\useKV[<trousseau>]{<clé>}| Il faut noter que \begin{itemize} - \item si la \<clé> n'a pas été prédéfinie par \verb|\setKVdefault|, une erreur sera émise; + \item si la \<clé> n'a pas été définie, une erreur sera émise; \item si la \<clé> est booléenne, le texte «\texttt{true}» ou «\texttt{false}» sera renvoyé; \item il faut 2 développements à \verb|\useKV[<trousseau>]{<clé>}| pour donner la \<valeur> associée à la \<clé>. \end{itemize} -\exemple|\setKVdefault[foo]{nombre = 5 , lettres= AB \textit{CD} , mon bool} -a) \useKV[foo]{nombre}.\qquad b) \useKV[foo]{lettres}.\qquad c) \useKV[foo]{mon bool}.\par +\exemple|\setKV[foo]{nombre = 5 , lettres= AB \textit{CD} , mon bool} +a) \useKV[foo]{nombre}.\qquad b) \useKV[foo]{lettres}.\qquad c) \useKV[foo]{mon bool}. + \setKV[foo]{lettres = X Y Z \textbf{123} } a) \useKV[foo]{nombre}.\qquad b) \useKV[foo]{lettres}.\qquad c) \useKV[foo]{mon bool}.| -\paragraph{La macro \texttt{\char`\\useKVdefault}} -L'exécution de cette macro par \verb|\useKVdefault[<trousseau>]| réinitialise toutes les \<clés> du \<trousseau> aux \<valeurs> qui ont été définies lors de l'exécution \verb|\setKVdefault|. +\paragraph{La macro \texttt{\char`\\restoreKV}} +La macro \verb|\restoreKV[<trousseau>]| réinitialise toutes les \<clés> du \<trousseau> aux \<valeurs> qui ont été définies lors de l'exécution \verb|\setKVdefault|. La macro \verb|\useKVdefault[<trousseau>]| lui est équivalente. \paragraph{La macro \texttt{\char`\\ifboolKV}} Cette macro permet, selon la valeur d'une \<clé booléenne>, d'exécuter un des deux \<codes> donnés. La syntaxe est -\code|\ifboolKV[<trousseau>]{<clé>}{<code si "true">}{<code si "false>}| + \code|\ifboolKV[<trousseau>]{<clé>}{<code si "true">}{<code si "false>}| La macro est purement développable, elle nécessite 2 développements pour donner l'un des deux codes, et exige que la \<clé> soit booléenne sans quoi un message d'erreur est émis. \paragraph{La macro \texttt{\char`\\showKV}} Cette commande écrit dans le fichier \texttt{log} la \<valeur> assignée à une \<clé> d'un \<trousseau>: -\code|\showKV[<trousseau>]{<clé>}| + \code|\showKV[<trousseau>]{<clé>}| Si la \<clé> n'est pas définie, «\texttt{not defined}» est affiché dans le fichier log. +\section{Code} +En plus d'une \<valeur>, un \<code> arbitraire peut être assigné à n'importe quelle \<clé>. Pour ce faire, on écrit +\begin{center} \verb|\defKV[<trousseau>]{<clé 1>=<code 1>,<clé 2>=<code 2>,...,<clé n>=<code n>}| +\end{center} +Chaque \<code> peut contenir \verb|#1| qui représente la \<valeur> de la \<clé>. Ce \<code> est exécuté lorsque une \<valeur> est assignée à la \<clé> avec \verb|\setKV|, \verb|\setKVdefault| ou \verb|\restoreKV|. +\bigbreak + +Ainsi déclarer + \code|\defKV[x]{ mykey = \def\foo{\textbf{#1}}| +va définir une macro \verb|\foo| dès que la \<clé> «\texttt{mykey}» va être définie (ou redéfinie) et donc, si l'on écrit + \code|\setKV[x]{ mykey = bonjour }| +le code qui est exécuté en coulisses est + \code|\long\def\foo{\textbf{bonjour}}| + +\exemple|\defKV[x]{ mykey = \def\foo{\textbf{#1}} } +\setKV[x]{ mykey = bonjour }% définition +1) \meaning\foo\par +2) \useKV[x]{ mykey } + +\setKV[x]{ mykey = hello }% redéfinition +3) \meaning\foo\par +4) \useKV[x]{ mykey }| + +La macro \verb|\testboolKV| permet de tester, par exemple dans un \<code>, si son argument est «true» ou «false» + \code|\testboolKV{<argument>}{<code si true>}{<code si false>}| + +La macro est purement développable, elle nécessite 2 développements pour donner l'un des deux codes, et exige que l'\<argument> soit booléen sans quoi un message d'erreur est émis. + +\exemple|\defKV[x]{ x = \def\test{\testboolKV{#1}{test positif}{test négatif}}} +\setKV[x]{ x = true} +1) \test + +\setKV[x]{ x= false} +2) \test| +Toute autre valeur que «\verb|true|» ou «\verb|false|» génèrera un message d'erreur. + \section{Un exemple d'utilisation} -Voici comment on pourrait programmer une macro qui affiche un cadre sur une ligne. Pour cela les \<clés> suivantes seront utilisées: +Voici comment on pourrait programmer une macro qui affiche un cadre sur une ligne, grâce à la macro \verb|\fbox| et l'environnement \verb|center| de \LaTeX. Pour cela les \<clés> suivantes seront utilisées: \begin{itemize} \item le booléen \texttt{inline} qui affichera le cadre dans le texte s'il est vrai et sur une ligne dédié s'il est faux; - \item \texttt{left code} et \texttt{right code} qui sont deux codes exécutés avant et après le cadre si le booléen est faux (par défaut : \verb|\hfill| et \verb|\hfill| pour un centrage sur la ligne); \item \texttt{sep} qui est une dimension mesurant la distance entre le texte et le cadre (par défaut \texttt{3pt}); - \item \texttt{width} qui est la largeur des traits du cadre (par défaut \texttt{0.5pt}). + \item \texttt{width} qui est la largeur des traits du cadre (par défaut \texttt{0.5pt}); + \item \texttt{style} qui contient le code exécuté avant le texte. \end{itemize} -\exemple|\setKVdefault[frame]{inline , left code = \hfill, right code = \hfill, sep = 3pt, width=0.5pt } +Une première façon de faire, sans recours à \verb|\defKV|; +\exemple|\setKVdefault[frame]{ + sep = 3pt, + line width = 0.5pt, + style = \bfseries, + inline + } +\newcommand\frametxt[2][]{% + \restoreKV[frame]% revenir au valeurs par défaut + \setKV[frame]{#1}% lit les arguments optionnels + \fboxsep = \useKV[frame]{sep} + \fboxrule= \useKV[frame]{line width} + \ifboolKV[frame]{inline} + {} + {\begin{center}}% + \fbox{\useKV[frame]{style}#2}% + \ifboolKV[frame]{inline} + {} + {\end{center}}% +} +Un essai en ligne par défaut \frametxt{essai} puis un autre \frametxt[sep=5pt,line width=2pt]{essai} +et un dernier \frametxt[sep=1pt,style=\itshape]{essai}. + +Un essai hors ligne : \frametxt[inline = false, style=\bfseries\color{red}]{essai centré}| + +Dans l'exemple repris ci-dessous et grâce à \verb|\defKV|, on stocke tous les paramètres lors de leur assignation. Il y a bien moins de verbosité dans le code de \verb|frametxt| ce qui le rend plus léger et plus lisible. + +\exemple|\defKV[frame]{% + sep = {\fboxsep = #1 }, + line width = {\fboxrule= #1 }, + inline = \testboolKV{#1} + {\def\hookpre{}\def\hookpost{}} + {\def\hookpre{\begin{center}}\def\hookpost{\end{center}}}, + style = \def\fstyle{#1} +} +\setKVdefault[frame]{ + sep = 3pt, + line width = 0.5pt, + style = \bfseries, + inline + } \newcommand\frametxt[2][]{% + \restoreKV[frame]% revenir au valeurs par défaut \setKV[frame]{#1}% lit les arguments optionnels - \ifboolKV[frame]{inline}{}{\par\noindent\useKV[frame]{left code}}% - \fboxsep=\useKV[frame]{sep}\relax - \fboxrule=\useKV[frame]{width}\relax - \fbox{#2}% - \ifboolKV[frame]{inline}{}{\useKV[frame]{right code}\null\par}% + \hookpre + \fbox{\fstyle #2}% + \hookpost } -Un essai en ligne par défaut \frametxt{essai} puis un autre \frametxt[sep=5pt,width=2pt]{essai} -et un dernier \frametxt[sep=0.5pt]{essai}. +Un essai en ligne par défaut \frametxt{essai} puis un autre \frametxt[sep=5pt,line width=2pt]{essai} +et un dernier \frametxt[sep=1pt,style=\itshape]{essai}. -\useKVdefault[frame]% revenir au valeurs par défaut -Un essai centré \frametxt[inline = false]{essai centré} -un autre fer à gauche \frametxt[left code={}]{essai à gauche} -un dernier indenté \frametxt[left code=\hskip 5em, right code={}, sep=1pt, width=2pt]{essai indenté}| +Un essai hors ligne : \frametxt[inline = false, style=\bfseries\color{red}]{essai centré}| \section{Le code} @@ -240,7 +305,7 @@ Le code ci-dessous est l'exact verbatim du fichier \verb|simplekv.tex| : \lstinputlisting[ language=TeX, - moretexcs={unless,ifcsname,ifdefined,detokenize,numexpr,dimexpr,glueexpr,unexpanded}, + moretexcs={unless,ifcsname,ifdefined,detokenize,numexpr,dimexpr,glueexpr,unexpanded,expanded}, basicstyle=\small\ttfamily\color{black!25}, identifierstyle=\bfseries\color{white},% backgroundcolor=\color{black!85}, @@ -264,7 +329,7 @@ Le code ci-dessous est l'exact verbatim du fichier \verb|simplekv.tex| : numbersep=1em, classoffset=1, alsoletter={\_}, - morekeywords={setKVdefault,setKV,useKVdefault,useKV,ifboolKV,}, + morekeywords={setKVdefault,setKV,useKVdefault,useKV,ifboolKV,defKV,testboolKV,showKV}, keywordstyle=\bfseries\color{red!85!black}, classoffset=0, ]{simplekv.tex} diff --git a/Master/texmf-dist/tex/generic/simplekv/simplekv.sty b/Master/texmf-dist/tex/generic/simplekv/simplekv.sty index 979276c0a6e..957f9ea0b44 100644 --- a/Master/texmf-dist/tex/generic/simplekv/simplekv.sty +++ b/Master/texmf-dist/tex/generic/simplekv/simplekv.sty @@ -1,4 +1,5 @@ % !TeX encoding = ISO-8859-1 +\def\skvfromSTY{} \input simplekv.tex \ProvidesPackage{simplekv}[\skvdate\space v\skvver\space Simple keyval package (CT)] \endinput
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/simplekv/simplekv.tex b/Master/texmf-dist/tex/generic/simplekv/simplekv.tex index d4ca63d9ebd..b1e2d3b59be 100644 --- a/Master/texmf-dist/tex/generic/simplekv/simplekv.tex +++ b/Master/texmf-dist/tex/generic/simplekv/simplekv.tex @@ -7,9 +7,9 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \def\skvname {simplekv} % -\def\skvver {0.1} % +\def\skvver {0.2} % % % -\def\skvdate {2017/08/08} % +\def\skvdate {2020/04/27} % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % @@ -27,11 +27,10 @@ % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Christian Tellechea -% Copyright : Christian Tellechea 2017 % email: unbonpetit@netc.fr % Commentaires, suggestions et signalement de bugs bienvenus ! % Comments, bug reports and suggestions are welcome. -% Copyright: Christian Tellechea 2017 +% Copyright: Christian Tellechea 2017-2020 % -------------------------------------------------------------------- % L'extension simplekv est composée des 5 fichiers suivants : % - code : simplekv (.tex et .sty) @@ -39,284 +38,157 @@ % - fichier lisezmoi : README % -------------------------------------------------------------------- -\expandafter\edef\csname skv_restorecatcode\endcsname{\catcode`\noexpand\_=\the\catcode`\_\relax} +%########################################## +%################ Préalable ############### +%########################################## +\csname skvloadonce\endcsname +\let\skvloadonce\endinput +\ifdefined\skvfromSTY\else + \immediate\write -1 {% + Package: \skvname\space\skvdate\space v\skvver\space Simple keyval package (CT)% + }% +\fi +%########################################## +%############ Gestion catcodes ############ +%########################################## +\begingroup + \def\X#1{\catcode\number`#1=\number\catcode`#1\relax} + \expandafter\xdef\csname skv_restorecatcode\endcsname{\X\,\X\=\X\_} +\endgroup \catcode`\_11 - -%################################################ -%################################################ -% Cette macro est équivalente à 0 et sert notamment à stopper le développement -% de \romannumeral +\chardef\skv_other12 +\catcode`\,\skv_other\catcode`\=\skv_other +%########################################## +%############ Macros auxilaires ########### +%########################################## \chardef\skv_stop 0 - -% Définition du quark, notamment inséré à la fin d'une liste pour en reconnaitre -% la fin et stopper la récursivité -\def\skv_quark{\skv_quark} - -% Voici les macros habituelles de sélection d'arguments \long\def\skv_first#1#2{#1} \long\def\skv_second#1#2{#2} - -% Voici la macro pour 1-développer ou 2-développer le 2e argument (le 1er étant -% dépouillé des accolades) -% \skv_exparg{<a>}{<b>} devient <a>{<b>} -% \skv_eearg{<a>}{<b>} devient <a>{**<b>} -\long\def\skv_exparg#1#2{\expandafter\skv_exparg_i\expandafter{#2}{#1}}% -\long\def\skv_eearg#1#2{\expandafter\expandafter\expandafter\skv_exparg_i\expandafter\expandafter\expandafter{#2}{#1}}% -\long\def\skv_exparg_i#1#2{#2{#1}} - -% Et la macro pour 1-développer le 2e argument (le 1er et le 2e argument sont -% dépouillés des accolades)% -% \skv_expafter{<a>}{<b>} devient <a><*b> -\long\def\skv_expafter#1#2{\expandafter\skv_expafter_i\expandafter{#2}{#1}} +\long\def\skv_gob#1{} +\long\def\skv_exe#1{#1} +\expandafter\def\expandafter\skv_gobspace\space{}% pour garder la compatibilité +\long\def\skv_earg#1#2{\expandafter\skv_earg_i\expandafter{#2}{#1}}\let\skv_exparg\skv_earg +\long\def\skv_eearg#1#2{\expandafter\expandafter\expandafter\skv_earg_i\expandafter\expandafter\expandafter{#2}{#1}} +\long\def\skv_earg_i#1#2{#2{#1}} +\long\def\skv_expafter#1#2{\expandafter\skv_expafter_i\expandafter{#2}{#1}}% {<a>}{<b>} devient <a><*b> \long\def\skv_expafter_i#1#2{#2#1} - -% Enfin, la macro pour former le nom du 2e argument (le 1er est dépouillé des -% accolades) -% \skv_argcsname{<a>}{<b>} devient <a>\<b> -\def\skv_argcsname#1#{\skv_argcsname_i{#1}} -\def\skv_argcsname_i#1#2{\skv_expafter{#1}{\csname#2\endcsname}} - -\def\skv_eaddtomacro#1#2{\skv_exparg{\skv_exparg{\def#1}}{\expandafter#1#2}} - -%################################################ -%################ macros de test ################ -%################################################ -% Voici quelques macros à sélection d'arguments pour les tests \def\skv_ifcsname#1{\ifcsname#1\endcsname\expandafter\skv_first\else\expandafter\skv_second\fi} \long\def\skv_ifx#1{\ifx#1\expandafter\skv_first\else\expandafter\skv_second\fi} -\long\def\skv_ifempty#1{\skv_exparg\skv_ifx{\expandafter\relax\detokenize{#1}\relax}} - -% Ces macros sont utiles pour \skv_removeextremespaces, qui retire les -% espaces extrêmes de son argument -% Voir codes 320-324 (http://progtex.fr/wp-content/uploads/2014/09/code.txt) -% et pages 339-343 de "Apprendre à programmer en TeX" -\long\def\skv_ifspacefirst#1{\expandafter\skv_ifspacefirst_i\detokenize{#10} \_nil} -\long\def\skv_ifspacefirst_i#1 #2\_nil{\skv_ifempty{#1}} -\expandafter\def\expandafter\skv_gobspace\space{} -\def\skv_removefirstspaces{\romannumeral\skv_removefirstspaces_i} -\long\def\skv_removefirstspaces_i#1{\skv_ifspacefirst{#1}{\expandafter\skv_removefirstspaces_i\expandafter{\skv_gobspace#1}}{\skv_stop#1}} -\begingroup - \catcode0 12 - \long\gdef\skv_removelastspaces#1{\romannumeral\skv_removelastspaces_i#1^^00 ^^00\_nil} - \long\gdef\skv_removelastspaces_i#1 ^^00{\skv_removelastspaces_ii#1^^00} - \long\gdef\skv_removelastspaces_ii#1^^00#2\_nil{\skv_ifspacefirst{#2}{\skv_removelastspaces_i#1^^00 ^^00\_nil}{\skv_stop#1}} -\endgroup -\long\def\skv_removeextremespaces#1{% - \romannumeral\expandafter\expandafter\expandafter\skv_removelastspaces\expandafter\expandafter\expandafter - {\expandafter\expandafter\expandafter\skv_stop\skv_removefirstspaces{#1}}% +\long\def\skv_ifempty#1{\skv_ifempty_i#1\_nil\_nil\skv_second\skv_first\__nil}% +\long\def\skv_ifempty_i#1#2\_nil#3#4#5\__nil{#4} +\def\skv_stripsp#1{% +\long\def\skv_stripsp##1##2{\expanded{\skv_stripsp_i\_marksp##2\__nil\_marksp#1\_marksp\_nil{##1}}}% +\long\def\skv_stripsp_i##1\_marksp#1##2\_marksp##3\_nil{\skv_stripsp_ii##3##1##2\__nil#1\__nil\_nil}% +\long\def\skv_stripsp_ii##1#1\__nil##2\_nil{\skv_stripsp_iii##1##2\_nil}% +\long\def\skv_stripsp_iii##1##2\__nil##3\_nil##4{\unexpanded{##4{##2}}}% +}\skv_stripsp{ } +%########################################## +%########## Macros de définition ########## +%########################################## +\def\setKVdefault{\let\skv_find_kv_i\skv_find_kv_nocode\skv_readKV\skv_exe} +\def\setKV {\let\skv_find_kv_i\skv_find_kv_nocode\skv_readKV\skv_gob} +\def\defKV {\let\skv_find_kv_i\skv_find_kv_code \skv_readKV\skv_gob} +\def\skv_readKV{% + \edef\skv_restorecatcode{\catcode44=\the\catcode44 \relax\catcode61=\the\catcode61 \relax}% + \catcode44\skv_other\catcode61\skv_other + \skv_readKV_i } - -%################################################ -%############## système clé/valeur ############## -%################################################ -% Ceci est le booléen indiquant si la lecture de <clés>=<valeurs> définit les -% <clés> _par défaut_ ou qu'il s'agit d'une _redéfinition_ des <clés> déjà -% existantes -\newif\ifskv_default - -% macros chapeau appelant la même macro avec le booléen préalablement défini -\def\setKVdefault{\skv_defaulttrue\skv_readKV} -\def\setKV{\skv_defaultfalse\skv_readKV} - -% L'argument obligatoire #1 est le nom du <trousseau> et #2 est l'ensemble -% des <clés>=<valeurs> -\def\skv_readKV[#1]#2{% - \skv_ifempty{#2} -% Si aucune <clés>=<valeurs> alors qu'on définit les <valeurs> par défaut, -% message d'erreur et on s'arrête là - {\ifskv_default\errmessage{No key/val found, no default key/val defined}\fi} -% Sinon, initialiser à <vide> la macro \skv_[<trousseau>] uniquement si on -% créé les <valeurs> par défaut - {\ifskv_default\skv_argcsname\let{skv_[#1]}\empty\fi -% Puis on passe aux choses sérieuses, on va lire un par un tous les éléments -% <clé>=<valeur> (contenus dans #2) en mettant le quark comme dernier couple -% pour montrer la fin de la liste - \skv_readKV_i[#1]#2,\skv_quark,% - }% +\long\def\skv_readKV_i#1[#2]#3{% + #1{\expandafter\def\csname skv_[#2]\endcsname{#3}}% exécute (si \defKV) ou pas + \def\skv_setname{#2}% + \skv_readKV_ii#3,\__,% + \skv_restorecatcode } +\long\def\skv_readKV_ii#1,{\skv_readKV_iii\skv_find_kv#1=true=\_nil\skv_find_kv\__\__nil}% si #1=\__ ne rien faire sinon \skv_find_kv#1=true=\_nil +\long\def\skv_readKV_iii#1\skv_find_kv\__#2\__nil{#1} -\def\skv_readKV_i[#1]#2,{% -% #2 est le premier couple "<clé>=<valeur>" de la liste qui reste à traiter : -% tout d'abord, on se débarrasse des espaces extrêmes - \skv_eearg{\def\__temp}{\skv_removeextremespaces{#2}}% -% Si ce qui en résulte est égal au <quark>, - \skv_ifx{\__temp\skv_quark} -% alors, on a fini et on ne fait rien (fin du processus) - {} -% Sinon, si ce qui en résulte est vide (le couple "<clé>=<valeur>" était donc -% vide ou composé d'un espace) - {\skv_ifx{\__temp\empty} -% On a fini et on ne fait rien (fin du processus) - {} -% dans le cas contraire, on va isoler la <clé> et la <valeur> du couple lu en -% prenant soin de mettre à la fin "=<quark>" pour se prémunir du cas où -% "<clé>=<valeur>" ne contient que la "<clé>" et pas de signe "=", ce qui -% ferait planter la macro à arguments délimités - {\expandafter\skv_find_kv\__temp=\skv_quark\_nil[#1]% - }% -% Lorsque la <clé> et la <valeur> est trouvée et stockée, recommencer et aller -% lire le prochain couple "<clé>=<valeur>" - \skv_readKV_i[#1]% - }% +\long\def\skv_find_kv#1=#2=#3\_nil{% + \edef\__key{_[\skv_setname]_\skv_stripsp\detokenize{#1}}% + \skv_stripsp\skv_find_kv_i{#2}% + \skv_readKV_ii } - -% Voici la macro à arguments délimités à qui on a transmis -% <clé>=<valeur>=<quark> (si <clé>=<valeur> est l'élément lu) -% ou -% <clé>=<quark> (si <clé> est seule) -% et qui va isoler la <clé> de la <valeur>. -\def\skv_find_kv#1=#2\_nil[#3]{% -% #1 est ce qui se trouve avant le _premier_ signe "=" et -% #2 est ce qui se trouve entre le premier signe "=" et le \_nil -% Pour la <clé>, pas de problème, c'est _obligatoirement_ ce qui est avant le -% signe "=", que ce signe soit présent dans le couple lu ou pas puisqu'on y a -% rajouté "=<quark>". -% On élimine les espaces extrêmes pour obtenir la <clé> définitive stockée dans -% \__key (il faut 2-développer \skv_removeextremespaces pour qu'elle donne son -% argument sans espace extrême) - \edef\__key{\detokenize\expandafter\expandafter\expandafter{\skv_removeextremespaces{#1}}}% -% Pour la <valeur>, on lui ôte d'abord les espaces extrêmes - \skv_eearg{\def\__val}{\skv_removeextremespaces{#2}}% - \skv_ifx{\__val\skv_quark} -% Si elle est égale au <quark>, alors la <valeur> vaut "true" - {\def\__val{true}}% -% Sinon, ôter "=<quark>" de la fin de l'argument #2, éliminer les espaces -% extrêmes de ce qui en résulte et stocker le tout dans \__val (tout ceci est -% effectué par la macro \skv_find_val <valeur>=<quark>) - {\skv_find_val#2}% -% Si on lit les <clés>=<valeurs> par défaut, - \ifskv_default -% assigner à la macro "\skv_[<trousseau>]_<clé>" la <valeur> trouvée - \skv_argcsname\let{skv_[#3]_\detokenize\expandafter{\__key}}\__val -% Puis ajouter à la macro "\skv_[<trousseau>]", qui a été préalablement -% initialisée à <vide> : -% \def\skv_[<trousseau>]_<clé>{<valeur>} - \skv_argcsname\skv_eaddtomacro{skv_[#3]}% - {\expandafter\def\csname skv_[#3]_\detokenize\expandafter{\__key}\expandafter\endcsname\expandafter{\__val}}% -% C'est selon ce hashage que sont enregistrés les couples <clé>/<valeur> : les -% <clés> sont contenues dans les noms des macros tandis que les <valeurs> sont -% les textes de remplacement de ces macros. -% C'est rapide et simple : -% a) pour trouver une <valeur> d'après sa <clé>, il suffit de développer la -% macro \skv_[<trousseau>]_<clé> -% b) pour redéfinir une <clé>, il suffit de redéfinir cette macro avec la -% nouvelle <valeur> -% c) il est facile de vérifier qu'une <clé> existe en vérifiant que la macro -% associée est définie, la primitive \ifcsname le fait très bien -% d) en revanche, on ne peut pas faire de recherche _inverse_ de façon -% pratique : il est en effet plus difficile de trouver la (ou les) <clé> -% contenant une <valeur> donnée, mais cette limitation n'a pas grande -% importance ici (je ne sais pas si les autres systèmes de <clé>/<valeur> -% sont programmés de telle sorte que cela soit simple...) -% Bref, la macro "\skv_[<trousseau>]" contient donc _toutes_ les définitions -% des macros définissant les <clés>/<valeurs> _par défaut_ et exécuter -% "\skv_[<trousseau>]" remet donc toutes les <clés> à leur <valeur> par défaut. - \else -% Dans le cas où on _lit_ des nouvelles <valeurs> pour des <clés> - \skv_ifcsname{skv_[#3]_\__key} -% Si la <clé> existe (ssi la macro "\skv_[<trousseau>]_<clé>" est définie), -% alors assigner la <valeur> à cette macro - {\skv_argcsname\let{skv_[#3]_\__key}\__val}% -% Sinon, émettre un message d'erreur et ne rien faire de plus - {\errmessage{Key "\__key" is not defined: nothing is modified}}% +\long\def\skv_find_kv_nocode#1{% + \expandafter\def\csname skv\__key\endcsname{#1}%\__val% stocker la clé + \ifcsname skvcode\__key\endcsname% si le code correspondant existe + \csname skvcode\__key\endcsname{#1}% exécute le code \fi } +\long\def\skv_find_kv_code#1{% + \expandafter\def\csname skvcode\__key\endcsname##1{#1}% +} -% Cette macro à qui on a transmis "<valeur>=<quark>" ne garde que <valeur>, en -% ôte les espaces extrêmes et stocke le résultat dans \__val -\def\skv_find_val#1=\skv_quark{\skv_eearg{\def\__val}{\skv_removeextremespaces{#1}}} - -% Cette macro remet toutes les <clés> à leur <valeurs> par défaut en exécutant -% la macro "\skv_[<trousseau>]" -\def\useKVdefault[#1]{% +\def\restoreKV[#1]{% \skv_ifcsname{skv_[#1]} - {\csname skv_[#1]\endcsname} -% Si la macro "\skv_[<trousseau>]" n'existe pas, message d'erreur - {\errmessage{Undefined set of keys "#1"}}% + {\skv_eearg{\setKV[#1]}{\csname skv_[#1]\endcsname}} + {\errmessage{Undefined or not saved set of keys "#1"}}% } - -% Cette macro donne la <valeur> correspondant à la <clé> contenue dans #2 -\def\useKV[#1]#2{% -% Avec \romannumeral, la <valeur> sera obtenue après _2_ développements de -% \useKV[<trousseau>]{<clé>} - \romannumeral\skv_ifempty{#2} -% Si la <clé> est vide, message d'erreur (il ne peut y avoir de <valeur> -% associée à une <clé> vide) - {\skv_stop\errmessage{Key name missing}} - {\skv_ifcsname{skv_[#1]_\skv_removeextremespaces{#2}} -% Si la macro "\skv_[<trousseau>]_<clé>" existe, 2-développer le \csname pour -% avoir la <valeur> - {\expandafter\expandafter\expandafter\skv_stop\csname skv_[#1]_\skv_removeextremespaces{#2}\endcsname} -% Sinon, message d'erreur - {\skv_stop\errmessage{Key "\skv_removeextremespaces{#2}" not defined}}% - }% +\let\useKVdefault\restoreKV +%########################################## +%############## Macro \useKV ############## +%########################################## +\def\useKV[#1]#2{\expanded{\skv_stripsp{\useKV_i[#1]}{#2}}} +\def\useKV_i[#1]#2{\expandafter\useKV_ii\csname skv_[#1]_#2\endcsname{#2}} +\def\useKV_ii#1#2{% + \ifdefined#1\unexpanded\expandafter{#1}% + \else \errmessage{Key "#2" not defined}% + \fi } - -% Voici une macro purement développable qui teste si #2 (la <clé> du <trousseau> -% #1) est égale à "true" ou à "false" et selon l'issue, exécute le 1er ou 2e -% argument qui suit (arguments appelés <vrai> et <faux>) -\def\ifboolKV[#1]#2{% -% Cette macro donnera un des 2 arguments <vrai> ou <faux> en _2_ développements -% grâce au \romannumeral - \romannumeral\skv_ifempty{#2} -% Si la <clé> est vide, message d'erreur - {\skv_stop\errmessage{Key name missing}\skv_second} - {\skv_ifcsname{skv_[#1]_\skv_removeextremespaces{#2}} -% Si la <clé> débarrassée de ses espaces extrêmes existe, tester son contenu - {\skv_eearg\ifboolKV_i{\csname skv_[#1]_\skv_removeextremespaces{#2}\endcsname}} -% Sinon, message d'erreur - {\skv_stop\errmessage{Key "\skv_removeextremespaces{#2}" not defined}\skv_second}% +%########################################## +%############# Macros de test ############# +%########################################## +\def\ifboolKV[#1]#2{\romannumeral\skv_stripsp{\ifboolKV_i[#1]}{#2}} +\def\ifboolKV_i[#1]#2{% + \skv_ifempty{#2} + {\skv_stop\errmessage{Empty argument is not a valid boolean}\skv_second + } + {\skv_ifcsname{skv_[#1]_#2} + {\skv_eearg\ifboolKV_ii{\csname skv_[#1]_#2\endcsname}} + {\skv_stop\errmessage{Key "#2" not defined}\skv_second}% }% } - -% Cette macro teste si #1, qui est une <valeur>, vaut "true" ou "false" -\def\ifboolKV_i#1{% -% Tester d'abord si elle vaut "true" +\def\ifboolKV_ii#1{%% Cette macro teste si #1, qui est une <valeur>, vaut "true" ou "false" \skv_ifargtrue{#1} - {\expandafter\skv_stop\skv_first} + {\expandafter\skv_stop\skv_first + } {\skv_ifargfalse{#1} -% Puis si elle vaut "false" {\expandafter\skv_stop\skv_second} -% Si ni l'un ni l'autre, la <valeur> n'est pas un booléen acceptable {\skv_stop\errmessage{Value "#1" is not a valid boolean}\skv_second}% }% } -% La macro \skv_ifargtrue{<argument>} teste de façon purement développable si -% <argument> vaut "true" ou "false". -% Pour cela, on transmet à \skv_ifargtrue_i l'argument "<argument>true" qui est -% délimité par \_nil +\def\testboolKV#1{\romannumeral\skv_stripsp{\testboolKV_i}{#1}}% macro publique qui teste si #1 est <true> ou <false>, erreur sinon +\def\testboolKV_i#1{% + \skv_ifempty{#1} + {\skv_stop\errmessage{Empty argument is not a valid boolean}\skv_second} + {\skv_stripsp{\ifboolKV_ii}{#1}}% +} + \def\skv_ifargtrue#1{\skv_ifargtrue_i#1true\_nil} -% Dans la macro \skv_ifargtrue_i, l'argument #1 est ce qui se trouve avant -% "true" dans "<argument>true" : -% - s'il n'est pas vide, sélectionner l'argument <faux> -% - s'il est vide, cela signifie que <argument> commence par "true" ; il est -% donc de la forme "true<autre>" -% L'argument #2 est ce qui se trouve après "true" dans "true<autre>true", -% c'est donc "<autre>true". -% Pour être sûr que <autre> est <vide>, on transmet "<autre>true" à -% \skv_ifargtrue_ii qui teste si la réunion de ce qui est avant le -% premier "true" et ce qui est après est <vide> \def\skv_ifargtrue_i#1true#2\_nil{\skv_ifempty{#1}{\skv_ifargtrue_ii#2\_nil}\skv_second} \def\skv_ifargtrue_ii#1true#2\_nil{\skv_ifempty{#1#2}} - -% On procède de même pour tester "false" \def\skv_ifargfalse#1{\skv_ifargfalse_i#1false\_nil} \def\skv_ifargfalse_i#1false#2\_nil{\skv_ifempty{#1}{\skv_ifargfalse_ii#2\_nil}\skv_second} \def\skv_ifargfalse_ii#1false#2\_nil{\skv_ifempty{#1#2}} - -\def\showKV[#1]#2{% -% Ecrire dans le fichier log "Key [<trousseau>]<clé>=" - \immediate\write-1 {Key [#1]\skv_removeextremespaces{#2}=% - \skv_ifcsname{skv_[#1]_\skv_removeextremespaces{#2}} -% si la <clé> est définie, prendre le \meaning de la macro correspondante - {\expandafter\expandafter\expandafter\skv_show\expandafter - \meaning\csname skv_[#1]_\skv_removeextremespaces{#2}\endcsname} -% Sinon, afficher - {not defined}% - }% +%########################################## +%############# Macro \showKV ############## +%########################################## +\def\showKV[#1]#2{\expanded{\skv_stripsp{\showKV_i[#1]}{#2}}} +\def\showKV_i[#1]#2{% + \immediate\write-1 {% + ^^JKey\space\space[#1]#2=% + \skv_ifcsname{skv_[#1]_#2} + {\expandafter\expandafter\expandafter\skv_show\expandafter + \meaning\csname skv_[#1]_#2\endcsname + \skv_ifcsname{skvcode_[#1]_#2} + {^^JCode [#1]#2=\expandafter\expandafter\expandafter\skv_show\expandafter + \meaning\csname skvcode_[#1]_#2\endcsname + } + {}% + } + {not defined% + }% + ^^J\relax}% } -% Mange ce qui se trouve jusqu'à "->" dans le développement de \meaning \def\skv_show#1->{} \skv_restorecatcode \endinput @@ -327,3 +199,7 @@ Versions : |-----------------------------------------------------------------------------| | 0.1 | 08/08/2017 | Première version | |-----------------------------------------------------------------------------| +| 0.2 | 27/04/2020 | - Un <code> peut être assigné à une <clé> | +| | | - Correction de bugs | +| | | - Optimisations | +|-----------------------------------------------------------------------------|
\ No newline at end of file |