summaryrefslogtreecommitdiff
path: root/macros/generic/simplekv
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/generic/simplekv
Initial commit
Diffstat (limited to 'macros/generic/simplekv')
-rw-r--r--macros/generic/simplekv/README21
-rw-r--r--macros/generic/simplekv/simplekv-fr.pdfbin0 -> 329306 bytes
-rw-r--r--macros/generic/simplekv/simplekv-fr.tex271
-rw-r--r--macros/generic/simplekv/simplekv.sty4
-rw-r--r--macros/generic/simplekv/simplekv.tex329
5 files changed, 625 insertions, 0 deletions
diff --git a/macros/generic/simplekv/README b/macros/generic/simplekv/README
new file mode 100644
index 0000000000..d612d38b6b
--- /dev/null
+++ b/macros/generic/simplekv/README
@@ -0,0 +1,21 @@
+___________________________________
+
+ L'extension
+ simplekv
+
+ v0.1
+
+ 8 aout 2017
+___________________________________
+
+Authors : Christian Tellechea
+Maintainer: Christian Tellechea
+E-mail : unbonpetit@netc.fr (CT)
+ Commentaires, signalements de bugs et
+ suggestions bienvenus
+Licence : Released under the LaTeX Project Public License v1.3c or
+ later, see http://www.latex-project.org/lppl.txt
+
+----------------------------------------------------------------------
+
+A simple key/value system for TeX.
diff --git a/macros/generic/simplekv/simplekv-fr.pdf b/macros/generic/simplekv/simplekv-fr.pdf
new file mode 100644
index 0000000000..797171dd55
--- /dev/null
+++ b/macros/generic/simplekv/simplekv-fr.pdf
Binary files differ
diff --git a/macros/generic/simplekv/simplekv-fr.tex b/macros/generic/simplekv/simplekv-fr.tex
new file mode 100644
index 0000000000..c899feeb73
--- /dev/null
+++ b/macros/generic/simplekv/simplekv-fr.tex
@@ -0,0 +1,271 @@
+% !TeX encoding = ISO-8859-1
+% Ceci est la documentation du package "hlist"
+%
+% Fichier compilé avec pdflatex
+\documentclass[french,a4paper,10pt]{article}
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage[margin=2cm]{geometry}
+\usepackage[bottom]{footmisc}
+\usepackage{libertine,boites,tikz,enumitem,MnSymbol,babel,xspace,listings,simplekv}
+\usepackage[scaled=0.8]{luximono}
+\frenchbsetup{og=«,fg=»}
+\def\eTeX{\hbox{$\varepsilon$-\TeX}}
+\def\SKV{\texttt{\skvname}\xspace}
+\makeatletter
+\def\code{\expandafter\code@i\string}
+\def\code@i#1{%
+ \begingroup
+ \par\nobreak\medskip\parindent0pt
+ \leftskip.1\linewidth
+ \make@car@active\^^I{\leavevmode\space\space\space\space}%
+ \let\do\@makeother \dospecials
+ \ttfamily\small\@noligs
+ \make@car@active\<{\begingroup$\langle$\itshape}%
+ \make@car@active\>{$\rangle$\endgroup}%
+ \obeylines\obeyspaces
+ \def\code@ii##1#1{##1\par\medbreak\endgroup}%
+ \code@ii
+}
+\long\def\grab@toks#1\relax{\gdef\right@content{#1}}
+
+\newcommand\disable@lig[1]{%
+ \catcode`#1\active
+ \begingroup
+ \lccode`\~`#1\relax
+ \lowercase{\endgroup\def~{\leavevmode\kern\z@\string#1}}%
+}
+
+\newcommand\make@car@active[1]{%
+ \catcode`#1\active
+ \begingroup
+ \lccode`\~`#1\relax
+ \lowercase{\endgroup\def~}%
+}
+
+\newcommand\exemple{%
+ \begingroup
+ \parskip\z@
+ \exemple@}
+
+\newcommand\exemple@{%
+ \medbreak\noindent
+ \begingroup
+ \let\do\@makeother\dospecials
+ \make@car@active\ { {}}%
+ \make@car@active\^^M{\par\leavevmode}%
+ \make@car@active\^^I{\space\space}%
+ \make@car@active\,{\leavevmode\kern\z@\string,}%
+ \make@car@active\-{\leavevmode\kern\z@\string-}%
+ \make@car@active\>{\leavevmode\kern\z@\string>}%
+ \make@car@active\<{\leavevmode\kern\z@\string<}%
+ \@makeother\;\@makeother\!\@makeother\?\@makeother\:% neutralise frenchb
+ \exemple@@
+}
+
+\newcommand\exemple@@[1]{%
+ \def\@tempa##1#1{\exemple@@@{##1}}%
+ \@tempa
+}
+
+\newcommand\exemple@@@[1]{%
+ \xdef\the@code{#1}%
+ \endgroup
+ \begingroup
+ \fboxrule0.4pt \fboxsep=5pt
+ \let\breakboxparindent\z@
+ \def\bkvz@top{\hrule\@height\fboxrule}%
+ \def\bkvz@bottom{\hrule\@height\fboxrule}%
+ \let\bkvz@before@breakbox\relax
+ \def\bkvz@set@linewidth{\advance\linewidth\dimexpr-2\fboxrule-2\fboxsep\relax}%
+ \def\bkvz@left{\vrule\@width\fboxrule\kern\fboxsep}%
+ \def\bkvz@right{\kern\fboxsep\vrule\@width\fboxrule}%
+ \breakbox
+ \kern.5ex\relax
+ \begingroup
+ \ttfamily\small\the@code\par
+ \endgroup
+ \kern3pt
+ \hrule height0.1pt width\linewidth depth0.1pt
+ \vskip5pt
+ \newlinechar`\^^M\everyeof{\noexpand}\scantokens{#1}\par
+ \endbreakbox
+ \endgroup
+ \medbreak
+ \endgroup
+}
+\begingroup
+ \catcode`\<13 \catcode`\>13
+ \gdef\verb{\relax\ifmmode\hbox\else\leavevmode\null\fi
+ \bgroup
+ \verb@eol@error \let\do\@makeother \dospecials
+ \verbatim@font\@noligs
+ \catcode`\<13 \catcode`\>13 \def<{\begingroup$\langle$\itshape}\def>{\/$\rangle$\endgroup}%
+ \@ifstar\@sverb\@verb}
+\endgroup
+\def\longfrhlstdate@i#1/#2/#3\@nil{\number#3\relax\space \ifcase#2 \or janvier\or février\or mars\or avril\or mai\or juin\or juillet\or aout\or septembre\or octobre\or novembre\or décembre\fi\space#1}
+\edef\longfrhlstdate{\expandafter\longfrhlstdate@i\skvdate\@nil}
+\def\<#1>{$\langle$\textit{#1}$\rangle$}
+\makeatother
+
+\begin{document}
+\parindent=0pt
+\thispagestyle{empty}
+\begin{titlepage}
+ \begingroup
+ \centering
+ \null\vskip.25\vsize
+ {\large\bfseries L'extension pour \TeX/\LaTeX\par \Huge \skvname\par}
+ \bigbreak
+ v \skvver
+ \smallbreak
+ \longfrhlstdate
+ \vskip1.5cm
+ Christian \bsc{Tellechea}\par
+ \texttt{unbonpetit@netc.fr}\par
+ \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.
+\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
+
+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 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 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>.
+\end{itemize}
+
+\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.
+
+On écrit
+\begin{center} \verb|\setKVdefault[<trousseau>]{<clé 1>=<valeur 1>,<clé 2>=<valeur 2>,...,<clé i>=<valeur i>}|
+\end{center}
+
+Il faut noter que
+\begin{itemize}
+ \item l'argument entre accolades contenant les \<clés> et les \<valeurs> ne peut pas être vide;
+ \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 \<valeur> est omise, elle est comprise comme étant «\texttt{true}». Ainsi, écrire
+ \code|\setKVdefault[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|.
+\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é>}|
+
+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é> 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
+\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`\\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>}|
+
+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é>}|
+
+Si la \<clé> n'est pas définie, «\texttt{not defined}» est affiché dans le fichier log.
+
+\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:
+\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}).
+\end{itemize}
+
+\exemple|\setKVdefault[frame]{inline , left code = \hfill, right code = \hfill, sep = 3pt, width=0.5pt }
+\newcommand\frametxt[2][]{%
+ \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}%
+}
+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}.
+
+\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é}|
+
+
+\section{Le code}
+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},
+ basicstyle=\small\ttfamily\color{black!25},
+ identifierstyle=\bfseries\color{white},%
+ backgroundcolor=\color{black!85},
+ keywordstyle=\bfseries\color{orange},
+ commentstyle=\color{cyan!66},
+ columns=fixed,
+ alsoletter={\_},
+ tabsize=2,
+ extendedchars=true,
+ showspaces=false,
+ showstringspaces=false,
+ numbers=left,
+ numberstyle=\tiny\ttfamily\color{black},
+ breaklines=true,
+ prebreak={\hbox{$\rhookswarrow$}},
+ breakindent=3em,
+ breakautoindent=true,
+ xleftmargin=1em,
+ xrightmargin=0pt,
+ lineskip=0pt,
+ numbersep=1em,
+ classoffset=1,
+ alsoletter={\_},
+ morekeywords={setKVdefault,setKV,useKVdefault,useKV,ifboolKV,},
+ keywordstyle=\bfseries\color{red!85!black},
+ classoffset=0,
+ ]{simplekv.tex}
+\end{document} \ No newline at end of file
diff --git a/macros/generic/simplekv/simplekv.sty b/macros/generic/simplekv/simplekv.sty
new file mode 100644
index 0000000000..979276c0a6
--- /dev/null
+++ b/macros/generic/simplekv/simplekv.sty
@@ -0,0 +1,4 @@
+% !TeX encoding = ISO-8859-1
+\input simplekv.tex
+\ProvidesPackage{simplekv}[\skvdate\space v\skvver\space Simple keyval package (CT)]
+\endinput \ No newline at end of file
diff --git a/macros/generic/simplekv/simplekv.tex b/macros/generic/simplekv/simplekv.tex
new file mode 100644
index 0000000000..d4ca63d9eb
--- /dev/null
+++ b/macros/generic/simplekv/simplekv.tex
@@ -0,0 +1,329 @@
+% !TeX encoding = ISO-8859-1
+% Ce fichier contient le code commenté de l'extension "simplekv"
+%
+% IMPORTANT : pour que les commentaires s'affichent correctement,
+% ouvrir ce fichier avec l'encodage ISO-8859-1
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+\def\skvname {simplekv} %
+\def\skvver {0.1} %
+% %
+\def\skvdate {2017/08/08} %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% --------------------------------------------------------------------
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+%
+% % http://www.latex-project.org/lppl.txt
+%
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+% --------------------------------------------------------------------
+% 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
+% --------------------------------------------------------------------
+% L'extension simplekv est composée des 5 fichiers suivants :
+% - code : simplekv (.tex et .sty)
+% - manuel en français : simplekv-fr (.tex et .pdf)
+% - fichier lisezmoi : README
+% --------------------------------------------------------------------
+
+\expandafter\edef\csname skv_restorecatcode\endcsname{\catcode`\noexpand\_=\the\catcode`\_\relax}
+\catcode`\_11
+
+%################################################
+%################################################
+% Cette macro est équivalente à 0 et sert notamment à stopper le développement
+% de \romannumeral
+\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_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}}%
+}
+
+%################################################
+%############## 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,%
+ }%
+}
+
+\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]%
+ }%
+}
+
+% 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}}%
+ \fi
+}
+
+% 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]{%
+ \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"}}%
+}
+
+% 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}}%
+ }%
+}
+
+% 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}%
+ }%
+}
+
+% Cette macro teste si #1, qui est une <valeur>, vaut "true" ou "false"
+\def\ifboolKV_i#1{%
+% Tester d'abord si elle vaut "true"
+ \skv_ifargtrue{#1}
+ {\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\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}%
+ }%
+}
+% Mange ce qui se trouve jusqu'à "->" dans le développement de \meaning
+\def\skv_show#1->{}
+\skv_restorecatcode
+\endinput
+
+Versions :
+ _____________________________________________________________________________
+| Version | Date | Changements |
+|-----------------------------------------------------------------------------|
+| 0.1 | 08/08/2017 | Première version |
+|-----------------------------------------------------------------------------|