% !TeX encoding = UTF-8 % Ce fichier contient le code commenté de l'extension "simplekv" % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \def\skvname {simplekv} % \def\skvver {0.2c} % % % \def\skvdate {2023/10/02} % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % -------------------------------------------------------------------- % 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 % email: unbonpetit@netc.fr % Commentaires, suggestions et signalement de bugs bienvenus ! % Comments, bug reports and suggestions are welcome. % Copyright: Christian Tellechea 2017-2023 % -------------------------------------------------------------------- % 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 % -------------------------------------------------------------------- %########################################## %################ 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 \catcode`\, = 12 \catcode`\= = 12 %########################################## %############ Macros auxilaires ########### %########################################## \chardef\skv_stop 0 \long\def\skv_first#1#2{#1} \long\def\skv_second#1#2{#2} \long\def\skv_antefi#1\fi{\fi#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_eearg#1#2{\expandafter\expandafter\expandafter\skv_earg_i\expandafter\expandafter\expandafter{#2}{#1}} \long\def\skv_earg_i#1#2{#2{#1}} \def\skv_ifcsname#1{\ifcsname#1\endcsname\expandafter\skv_first\else\expandafter\skv_second\fi} \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{ } \def\skv_error#1{\errmessage{Package \skvname\space Error: #1.}} %########################################## %########## Macros de définition ########## %########################################## \def\setKVdefault{\let\skv_find_kv_ii\skv_find_kv_nocode\skv_readKV\skv_exe} \def\setKV {\let\skv_find_kv_ii\skv_find_kv_nocode\skv_readKV\skv_gob} \def\defKV {\let\skv_find_kv_ii\skv_find_kv_code \skv_readKV\skv_gob} \long\def\skv_readKV#1[#2]#3{% #1{\expandafter\def\csname skv_[#2]\endcsname{#3}}% exécute (si \setKVdefault) ou pas \def\skv__currentname{#2}% \skv_readKV_i#3,\skv_end,% } \long\def\skv_readKV_i#1,{% \skv_stripsp\skv_ifempty{#1}% Bugfix 0.2c : on ignore un truc vide entre 2 virgules {% \skv_readKV_i } {% \skv_readKV_ii\skv_find_kv#1=true=\_nil\skv_find_kv\skv_end\__nil% si #1=\skv_end ne rien faire sinon \skv_find_kv#1=true=\_nil }% } \long\def\skv_readKV_ii#1\skv_find_kv\skv_end#2\__nil{#1} \long\def\skv_find_kv#1={% \edef\skv__currentkey{_[\skv__currentname]_\skv_stripsp\detokenize{#1}}% \skv_find_kv_i{}% } \long\def\skv_find_kv_i#1=#2\_nil{% \expandafter\skv_stripsp\expandafter\skv_find_kv_ii\expandafter{\skv_gob#1}% \skv_readKV_i } \long\def\skv_find_kv_nocode#1{% \expandafter\def\csname skv\skv__currentkey\endcsname{#1}% stocker la valeur \ifcsname skvcode\skv__currentkey\endcsname \skv_antefi\csname skvcode\skv__currentkey\endcsname{#1}% \fi } \long\def\skv_find_kv_code{% \expandafter\def\csname skvcode\skv__currentkey\endcsname##1% } \def\restoreKV[#1]{% \skv_ifcsname{skv_[#1]} {% \skv_eearg{\setKV[#1]}{\csname skv_[#1]\endcsname}% } {% \skv_error{Undefined or not saved set of keys "#1"}% }% } \let\useKVdefault\restoreKV %########################################## %############## Macro \useKV ############## %########################################## \def\useKV[#1]{\romannumeral\skv_stripsp{\useKV_i[#1]}} \def\useKV_i[#1]#2{% \ifcsname skv_[#1]_\detokenize{#2}\endcsname \expandafter\expandafter\expandafter\skv_stop\csname skv_[#1]_\detokenize{#2}\expandafter\endcsname \else \skv_stop \skv_error{Key "\detokenize{#2}" not defined in group of keys "#1"}% \fi } %########################################## %############# Macros de test ############# %########################################## \def\ifboolKV[#1]{\romannumeral\skv_stripsp{\ifboolKV_i[#1]}} \def\ifboolKV_i[#1]#2{% \ifcsname skv_[#1]_\detokenize{#2}\endcsname \expandafter\expandafter\expandafter\ifboolKV_ii\csname skv_[#1]_\detokenize{#2}\expandafter\endcsname \expandafter\ifboolKV_ii \else \skv_stop \skv_error{Key "\detokenize{#2}" not defined in group of keys "#1"}% \expandafter\skv_second \fi } \def\ifboolKV_ii#1\ifboolKV_ii{%% Cette macro teste si #1, qui est une , vaut "true" ou "false" \skv_ifargtrue{#1} {% \expandafter\skv_stop \skv_first } {% \skv_ifargfalse{#1} {% \expandafter\skv_stop \skv_second } {% \skv_stop \skv_error{Value "\detokenize{#1}" is not a valid boolean}% \skv_second }% }% } \def\testboolKV{\romannumeral\skv_stripsp\testboolKV_i}% macro publique qui teste si #1 est ou , erreur sinon \def\testboolKV_i#1{% \skv_ifempty{#1} {% \skv_stop \skv_error{Empty argument is not a valid boolean} \skv_second } {% \ifboolKV_ii#1\ifboolKV_ii }% } \def\skv_ifargtrue#1{\skv_ifargtrue_i#1true\_nil} \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}} \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}} %########################################## %############# Macro \showKV ############## %########################################## \def\showKV[#1]{\skv_stripsp{\showKV_i[#1]}} \def\showKV_i[#1]#2{% \edef\skv__currentkey{_[#1]_\detokenize{#2}}% \immediate\write-1 {% ^^J% Key\space\space\detokenize{[#1]#2 -> }% \skv_ifcsname{skv\skv__currentkey} {% \showKV_ii{skv\skv__currentkey}% ^^J% Code \detokenize{[#1]#2 -> }% \skv_ifcsname{skvcode\skv__currentkey} {% \showKV_ii{skvcode\skv__currentkey}% } {% not defined% }% } {% not defined% }% ^^J% \relax}% } \def\showKV_ii#1{% \expandafter\expandafter\expandafter \skv_show\expandafter \meaning\csname#1\endcsname } \def\skv_show#1->{} \skv_restorecatcode \endinput Versions : _____________________________________________________________________________ | Version | Date | Changements | |-----------------------------------------------------------------------------| | 0.1 | 08/08/2017 | Première version | |-----------------------------------------------------------------------------| | 0.2 | 27/04/2020 | - Un peut être assigné à une | | | | - Correction de bugs | | | | - Optimisations | |-----------------------------------------------------------------------------| | 0.2a | 01/10/2022 | - vieux bug corrigé : \useKV envoie désormais une | | | | erreur si une clé n'est pas définie | | | | - la valeur n'est dépouillée que d'une accolade (et | | | | non pas de 2 comme auparavant) | | | | - quelques petits nettoyages, code en UTF8 | |-----------------------------------------------------------------------------| | 0.2b | 30/10/2022 | - messages d'erreur mieux formatés | | | | - détokénisée dans \ifboolKV et \showKV pour | | | | être cohérent avec \setKV et \useKV | |-----------------------------------------------------------------------------| | 0.2c | 02/10/2023 | - bug corrigé : si un item est vide, il est| | | | ignoré | | | | - quelques remaniements du code | |-----------------------------------------------------------------------------|