From 7f8fffa1c8b5b30f8e2a9fd4b76778147dbb9128 Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Tue, 28 Apr 2020 03:02:53 +0000
Subject: CTAN sync 202004280302

---
 macros/generic/simplekv/simplekv.tex | 374 ++++++++++++-----------------------
 1 file changed, 125 insertions(+), 249 deletions(-)

(limited to 'macros/generic/simplekv/simplekv.tex')

diff --git a/macros/generic/simplekv/simplekv.tex b/macros/generic/simplekv/simplekv.tex
index d4ca63d9eb..b1e2d3b59b 100644
--- a/macros/generic/simplekv/simplekv.tex
+++ b/macros/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
-- 
cgit v1.2.3

