summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-07-07 03:01:45 +0000
committerNorbert Preining <norbert@preining.info>2022-07-07 03:01:45 +0000
commitc925207bc17a56bf94a6e3d156db27042965136d (patch)
treeb5dc80f7f6791eba6121e1a44c1c2b9a4b46dbb2 /macros
parent9f9a07ef2eb0c1f25ce9afc7bb94928956c036ea (diff)
CTAN sync 202207070301
Diffstat (limited to 'macros')
-rw-r--r--macros/latex/contrib/inlinelabel/README.md19
-rw-r--r--macros/latex/contrib/inlinelabel/inlinelabel-en.md55
-rw-r--r--macros/latex/contrib/inlinelabel/inlinelabel-ja.md55
-rw-r--r--macros/latex/contrib/inlinelabel/inlinelabel.pdfbin0 -> 158341 bytes
-rw-r--r--macros/latex/contrib/inlinelabel/inlinelabel.sty46
-rw-r--r--macros/latex/contrib/inlinelabel/inlinelabel_example.tex11
-rw-r--r--macros/latex/contrib/postnotes/CHANGELOG.md7
-rw-r--r--macros/latex/contrib/postnotes/postnotes-code.pdfbin809579 -> 813102 bytes
-rw-r--r--macros/latex/contrib/postnotes/postnotes.dtx64
-rw-r--r--macros/latex/contrib/postnotes/postnotes.pdfbin177238 -> 178034 bytes
-rw-r--r--macros/latex/contrib/profcollege/doc/ProfCollege-doc.pdfbin8450619 -> 8577548 bytes
-rw-r--r--macros/latex/contrib/profcollege/latex/ProfCollege.sty1079
-rw-r--r--macros/latex/contrib/profcollege/metapost/PfCGeometrie.mp236
-rw-r--r--macros/latex/contrib/profcollege/metapost/PfCScratch.mp2
-rw-r--r--macros/luatex/generic/luakeys/README.md20
-rw-r--r--macros/luatex/generic/luakeys/luakeys-debug.sty2
-rw-r--r--macros/luatex/generic/luakeys/luakeys-debug.tex65
-rw-r--r--macros/luatex/generic/luakeys/luakeys-doc.pdfbin254353 -> 276812 bytes
-rw-r--r--macros/luatex/generic/luakeys/luakeys-doc.tex726
-rw-r--r--macros/luatex/generic/luakeys/luakeys.lua511
-rw-r--r--macros/luatex/generic/luakeys/luakeys.sty2
21 files changed, 2200 insertions, 700 deletions
diff --git a/macros/latex/contrib/inlinelabel/README.md b/macros/latex/contrib/inlinelabel/README.md
index e7acb7ca7e..14e2879a9f 100644
--- a/macros/latex/contrib/inlinelabel/README.md
+++ b/macros/latex/contrib/inlinelabel/README.md
@@ -1,27 +1,26 @@
-# Inlinelabel Package
+# inlinelabel
This package can assign equation numbers to inline equations. When Japanese is supported, you can switch to circled equation numbers.
-## System Requirements
+## Documents
-+ TeX format: LaTeX
-+ Prerequisite package: amsmath and refcount
-+ Prerequisite package with [circled] option: japanese-otf
-
-
-## Installation
-
-Move inlinelabel.sty file to $TEXMF/tex/latex/hideanswer.
+Documents for this pacakge are available in English and Japanese.
## License
This package released under [the MIT license](https://ctan.org/license/mit).
+(C) 2022 Yukoh KUSAKABE
+
## Revision History
++ Version 1.1 2022-07-07
+ + Rewrite README.
+ + Add the document (inlinelabel.pdf).
+ + Add the [luacircled] option.
+ Version 1.0 2022-06-28
+ The first public version.
diff --git a/macros/latex/contrib/inlinelabel/inlinelabel-en.md b/macros/latex/contrib/inlinelabel/inlinelabel-en.md
deleted file mode 100644
index dd726d5533..0000000000
--- a/macros/latex/contrib/inlinelabel/inlinelabel-en.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Inlinelabel Package
-
-This package can assign equation numbers to inline equations. When Japanese is supported, you can switch to circled equation numbers.
-
-
-## System Requirements
-
-+ TeX format: LaTeX
-+ Prerequisite package: amsmath and refcount
-+ Prerequisite package with [circled] option: japanese-otf
-
-
-## Installation
-
-Move inlinelabel.sty file to $TEXMF/tex/latex/hideanswer.
-
-
-## Usage
-
-### \inlinelabel{<label>}
-
-Put the inline equation number. Place it outside of the equation (outside of the $--$). Take the name of the label as an argument. Take a small margin before and after the text to make it look natural. If you don't want margins, use \inlinelabel*{<label>}.
-
-
-### Option [circled]
-
-Assuming you are using a Japanese environment. Switch to circled equation numbers. All equation numbers are rewritten, not just the inline equation numbers.
-
-
-### \circledref{<label>}
-
-Only valid when [circled] option is loaded.
-Refer to the circled equation number.
-
-
-### \equationref{<label>}
-
-Only valid when [circled] option is loaded.
-This macro is the same as \circledref{<label>}.
-
-
-## License
-
-This package released under [the MIT license](https://ctan.org/license/mit).
-
-
-## Revision History
-
-+ Version 1.0 2022-06-28
- + The first public version.
-
-
----
-
-[Yukoh KUSAKABE](https://twitter.com/metaphysicainfo) (screen-name) at [metaphysica.info](https://www.metaphysica.info/) \ No newline at end of file
diff --git a/macros/latex/contrib/inlinelabel/inlinelabel-ja.md b/macros/latex/contrib/inlinelabel/inlinelabel-ja.md
deleted file mode 100644
index a0e14fe403..0000000000
--- a/macros/latex/contrib/inlinelabel/inlinelabel-ja.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# Inlinelabel パッケージ
-
-このパッケージは,インライン数式に数式番号を振ることができます。また,日本語を扱えるときには,丸で囲まれた数式番号に切り替えることができます。
-
-
-## 前提条件
-
-+ TeX format: LaTeX
-+ Prerequisite package: amsmath and refcount
-+ Prerequisite package with [circled] option: japanese-otf
-
-
-## インストール
-
-inlinelabel.sty を $TEXMF/tex/latex/hideanswer (TeXが見つけられる場所)に置いてください。
-
-
-## 使用方法
-
-### \inlinelabel{<label>}
-
-インラインの数式番号を置きます。数式の外($--$の外)に置いてください。引数にラベルの名前を取ります。文章を自然に見せるために,前後に少しの余白を取ります。余白がいらないときは,\inlinelabel*{<label>} を使ってください。
-
-
-### Option [circled]
-
-あなたが日本語の環境を使用していることを前提とします。丸で囲まれた数式番号に切り替えます。インラインの数式番号だけでなく,すべての数式番号が書き換えられます。
-
-
-### \circledref{<label>}
-
-[circled] オプションを読み込んでいるときにのみ有効です。
-丸で囲まれた数式番号を参照します。
-
-
-### \equationref{<label>}
-
-[circled] オプションを読み込んでいるときにのみ有効です。
-\circledref{<label>} と同じです。
-
-
-## ライセンス
-
-このパッケージは[MITライセンス](https://ctan.org/license/mit)のもとで配布しています。
-
-
-## 更新履歴
-
-+ Version 1.0 2022-06-28
- + The first public version.
-
-
----
-
-[Yukoh KUSAKABE](https://twitter.com/metaphysicainfo) (screen-name) at [metaphysica.info](https://www.metaphysica.info/) \ No newline at end of file
diff --git a/macros/latex/contrib/inlinelabel/inlinelabel.pdf b/macros/latex/contrib/inlinelabel/inlinelabel.pdf
new file mode 100644
index 0000000000..67544ad66c
--- /dev/null
+++ b/macros/latex/contrib/inlinelabel/inlinelabel.pdf
Binary files differ
diff --git a/macros/latex/contrib/inlinelabel/inlinelabel.sty b/macros/latex/contrib/inlinelabel/inlinelabel.sty
index 93c4822c83..54f35259ff 100644
--- a/macros/latex/contrib/inlinelabel/inlinelabel.sty
+++ b/macros/latex/contrib/inlinelabel/inlinelabel.sty
@@ -10,11 +10,18 @@
%%
%
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{inlinelabel}[2022/06/28 v1.0]
+\ProvidesPackage{inlinelabel}[2022/07/07 v1.1]
%
% When you meet ''Package pxufont Error: You must load this package
% after 'otf'.'', move \usepackage{otf} to a forward row.
%
+%% \if@inlinelabel@nospace
+\newif\if@inlinelabel@nospace
+\@inlinelabel@nospacefalse
+%
+%% [nospace]
+\DeclareOption{nospace}{\@inlinelabel@nospacetrue}
+%
%% \if@inlinelabel@circled
\newif\if@inlinelabel@circled
\@inlinelabel@circledfalse
@@ -22,6 +29,14 @@
%% [circled]
\DeclareOption{circled}{\@inlinelabel@circledtrue}
%
+%% \if@inlinelabel@luacircled
+\newif\if@inlinelabel@luacircled
+\@inlinelabel@luacircledfalse
+%
+%% [luacircled]
+\DeclareOption{luacircled}{\@inlinelabel@luacircledtrue}
+%
+%
\ExecuteOptions{}
\ProcessOptions\relax
%
@@ -47,9 +62,38 @@
\fi
%%
%
+%% When [luacircled]
+\if@inlinelabel@luacircled
+%
+% for \ajMaru
+\RequirePackage{luatexja-otf}
+% for \getrefnumber
+\RequirePackage{refcount}
+%
+% renew tagform
+\def\tagform@#1{\maketag@@@{$\ldots\hspace*{-0.075em}$\ignorespaces\ajMaru{#1}\unskip\@@italiccorr}}%
+%
+%% \circledref{<label>}
+%% \equationref{<label>}
+\DeclareRobustCommand{\circledref}[1]{\mbox{\ajMaru{\getrefnumber{#1}}}}
+\DeclareRobustCommand{\equationref}[1]{\mbox{\ajMaru{\getrefnumber{#1}}}}
+%
+\fi
+%
+\if@inlinelabel@nospace
+%
+%% [nospace]\inlinelabel{<label>}
+\DeclareRobustCommand{\inlinelabel}{\@ifstar{\@inlinelabelstar}{\@inlinelabelnostar}}
+\DeclareRobustCommand{\@inlinelabelnostar}[1]{\refstepcounter{equation}\tagform@\theequation\expandafter\label{#1}}
+\DeclareRobustCommand{\@inlinelabelstar}[1]{\hspace{0.5em}\refstepcounter{equation}\tagform@\theequation\expandafter\label{#1}\hspace{0.5em}}
+%
+\else
+%
%% \inlinelabel{<label>}
\DeclareRobustCommand{\inlinelabel}{\@ifstar{\@inlinelabelstar}{\@inlinelabelnostar}}
\DeclareRobustCommand{\@inlinelabelstar}[1]{\refstepcounter{equation}\tagform@\theequation\expandafter\label{#1}}
\DeclareRobustCommand{\@inlinelabelnostar}[1]{\hspace{0.5em}\refstepcounter{equation}\tagform@\theequation\expandafter\label{#1}\hspace{0.5em}}
%
+\fi
+%
%% EOF \ No newline at end of file
diff --git a/macros/latex/contrib/inlinelabel/inlinelabel_example.tex b/macros/latex/contrib/inlinelabel/inlinelabel_example.tex
deleted file mode 100644
index bf70bcaf82..0000000000
--- a/macros/latex/contrib/inlinelabel/inlinelabel_example.tex
+++ /dev/null
@@ -1,11 +0,0 @@
-\documentclass[uplatex]{article}
-\usepackage{inlinelabel}
-\begin{document}
-$1=2$\inlinelabel{a}
-
-$1=2$\inlinelabel*{b}
-
-\ref{a}
-
-\ref{b}
-\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/postnotes/CHANGELOG.md b/macros/latex/contrib/postnotes/CHANGELOG.md
index 384af1bb2e..42e0f5f7f7 100644
--- a/macros/latex/contrib/postnotes/CHANGELOG.md
+++ b/macros/latex/contrib/postnotes/CHANGELOG.md
@@ -1,6 +1,11 @@
# Changelog
-## [Unreleased](https://github.com/gusbrs/postnotes/compare/v0.1.3...HEAD)
+## [Unreleased](https://github.com/gusbrs/postnotes/compare/v0.1.4...HEAD)
+
+## [v0.1.4](https://github.com/gusbrs/postnotes/compare/v0.1.3...v0.1.4) (2022-07-06)
+
+### Added
+- `zref-check` support.
## [v0.1.3](https://github.com/gusbrs/postnotes/compare/v0.1.2...v0.1.3) (2022-05-28)
diff --git a/macros/latex/contrib/postnotes/postnotes-code.pdf b/macros/latex/contrib/postnotes/postnotes-code.pdf
index b1af0cc1e0..c364f3c9b7 100644
--- a/macros/latex/contrib/postnotes/postnotes-code.pdf
+++ b/macros/latex/contrib/postnotes/postnotes-code.pdf
Binary files differ
diff --git a/macros/latex/contrib/postnotes/postnotes.dtx b/macros/latex/contrib/postnotes/postnotes.dtx
index 7124ed7d70..489c40bf5d 100644
--- a/macros/latex/contrib/postnotes/postnotes.dtx
+++ b/macros/latex/contrib/postnotes/postnotes.dtx
@@ -147,7 +147,7 @@
%
%
% \begin{macrocode}
-\ProvidesExplPackage {postnotes} {2022-05-28} {0.1.3}
+\ProvidesExplPackage {postnotes} {2022-07-06} {0.1.4}
{Endnotes for LaTeX}
% \end{macrocode}
%
@@ -1338,7 +1338,7 @@
{ content } \l_@@_print_content_tl
\cs_set:Npn \@currentcounter { postnotetext }
\int_set:Nn \c@postnotetext
- { \int_eval:n { \l_@@_print_counter_tl } }
+ { \l_@@_print_counter_tl }
\cs_set:Npx \@currentlabel
{ \p@postnote \l_@@_print_mark_tl }
\@@_hyperref_make_currentHref:n
@@ -1940,6 +1940,12 @@
%
% \section{Compatibility}
%
+% A dedicated temp variable for restoring data.
+%
+% \begin{macrocode}
+\tl_new:N \l_@@_restore_tmp_tl
+% \end{macrocode}
+%
% \subsection*{\cs{caption}}
%
% For \cs{caption}'s possible two passes. This catches more than just
@@ -2055,21 +2061,20 @@
% \end{macrocode}
% Restore \pkg{biblatex} variables for each note.
% \begin{macrocode}
- \tl_new:N \l_@@_biblatex_restore_tl
\AddToHook { postnotes/print/eachnote } [ postnotes ]
{
\@@_prop_get:nnN { \l_@@_print_note_id_tl }
- { biblatex@refsection } \l_@@_biblatex_restore_tl
- \int_set:Nn \c@refsection { \l_@@_biblatex_restore_tl }
+ { biblatex@refsection } \l_@@_restore_tmp_tl
+ \int_set:Nn \c@refsection { \l_@@_restore_tmp_tl }
\@@_prop_get:nnN { \l_@@_print_note_id_tl }
- { biblatex@refsegment } \l_@@_biblatex_restore_tl
- \int_set:Nn \c@refsegment { \l_@@_biblatex_restore_tl }
+ { biblatex@refsegment } \l_@@_restore_tmp_tl
+ \int_set:Nn \c@refsegment { \l_@@_restore_tmp_tl }
\@@_prop_get:nnN { \l_@@_print_note_id_tl }
- { biblatex@refcontextbool } \l_@@_biblatex_restore_tl
- \use:c { toggle \l_@@_biblatex_restore_tl } { blx@refcontext }
+ { biblatex@refcontextbool } \l_@@_restore_tmp_tl
+ \use:c { toggle \l_@@_restore_tmp_tl } { blx@refcontext }
\@@_prop_get:nnN { \l_@@_print_note_id_tl }
- { biblatex@refcontext } \l_@@_biblatex_restore_tl
- \blx@edef@refcontext { \l_@@_biblatex_restore_tl }
+ { biblatex@refcontext } \l_@@_restore_tmp_tl
+ \blx@edef@refcontext { \l_@@_restore_tmp_tl }
}
% \end{macrocode}
% Make \pkg{biblatex}'s \cs{mkbibendnote} use \cs{postnote}. This is very
@@ -2204,15 +2209,15 @@
\AddToHook { postnotes/print/eachnote } [ postnotes ]
{
\@@_prop_get:nnN { \l_@@_print_note_id_tl }
- { biblatex@refsection } \l_@@_biblatex_restore_tl
+ { biblatex@refsection } \l_@@_restore_tmp_tl
\tl_if_eq:NNF
- \l_@@_biblatex_restore_tl
+ \l_@@_restore_tmp_tl
\g_@@_biblatex_prev_refsection_tl
{
\int_set:Nn \c@blx@maxsection
- { \l_@@_biblatex_restore_tl - 1 }
+ { \l_@@_restore_tmp_tl - 1 }
\tl_gset_eq:NN \g_@@_biblatex_prev_refsection_tl
- \l_@@_biblatex_restore_tl
+ \l_@@_restore_tmp_tl
\group_begin:
\cs_set_eq:NN \label \use_none:n
\cs_set_eq:NN \blx@info \use_none:n
@@ -2308,6 +2313,35 @@
% \end{macrocode}
%
%
+% \subsection*{\pkg{zref-check}}
+%
+% \begin{macrocode}
+\AddToHook { package/zref-check/after }
+ {
+ \IfPackageAtLeastTF { zref-check } { 2022-07-05 }
+ {
+ \AddToHook { postnotes/store/note } [ postnotes ]
+ {
+ \prop_gput:cnx { \@@_data_name:e { \l_@@_note_id_tl } }
+ { zref-check@abschap } { \int_use:N \c@zc@abschap }
+ \prop_gput:cnx { \@@_data_name:e { \l_@@_note_id_tl } }
+ { zref-check@abssec } { \int_use:N \c@zc@abssec }
+ }
+ \AddToHook { postnotes/print/eachnote } [ postnotes ]
+ {
+ \@@_prop_get:nnN { \l_@@_print_note_id_tl }
+ { zref-check@abschap } \l_@@_restore_tmp_tl
+ \int_set:Nn \c@zc@abschap { \l_@@_restore_tmp_tl }
+ \@@_prop_get:nnN { \l_@@_print_note_id_tl }
+ { zref-check@abssec } \l_@@_restore_tmp_tl
+ \int_set:Nn \c@zc@abssec { \l_@@_restore_tmp_tl }
+ }
+ }
+ { }
+ }
+% \end{macrocode}
+%
+%
% \subsection*{\pkg{amsmath}}
%
% \begin{macrocode}
diff --git a/macros/latex/contrib/postnotes/postnotes.pdf b/macros/latex/contrib/postnotes/postnotes.pdf
index af17232cc1..6059ea2438 100644
--- a/macros/latex/contrib/postnotes/postnotes.pdf
+++ b/macros/latex/contrib/postnotes/postnotes.pdf
Binary files differ
diff --git a/macros/latex/contrib/profcollege/doc/ProfCollege-doc.pdf b/macros/latex/contrib/profcollege/doc/ProfCollege-doc.pdf
index 75069775ec..f2aa966d0e 100644
--- a/macros/latex/contrib/profcollege/doc/ProfCollege-doc.pdf
+++ b/macros/latex/contrib/profcollege/doc/ProfCollege-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/profcollege/latex/ProfCollege.sty b/macros/latex/contrib/profcollege/latex/ProfCollege.sty
index 45e407cf36..5221eebaa9 100644
--- a/macros/latex/contrib/profcollege/latex/ProfCollege.sty
+++ b/macros/latex/contrib/profcollege/latex/ProfCollege.sty
@@ -1,9 +1,8 @@
% Author : Christophe Poulain
% licence : Released under the LaTeX Project Public License v1.3c
% or later, see http://www.latex-project.org/lppl.txtf
-
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{ProfCollege}[2022/06/01 v0.99-p Aide pour l'utilisation de LaTeX au college]
+\ProvidesPackage{ProfCollege}[2022/07/01 v0.99-r Aide pour utiliser LaTeX au college]
\RequirePackage{verbatim}
@@ -190,9 +189,11 @@
}%
\newcommand\Lignespointilles[1]{%
- \xintFor* ##1 in {\xintSeq {1}{#1}}\do{%
- \pointilles\par%
- }%
+ \xintifboolexpr{#1>1}{%
+ \xintFor* ##1 in {\xintSeq {1}{#1}}\do{%
+ \pointilles\par%
+ }%
+ }{}%
}%
\newcommand\MultiCol[2]{%
@@ -337,6 +338,717 @@
}
%%%
+% Représenter un entier
+%%%
+\setKVdefault[ClesREntier]{Echelle=1,Unite=false,Compact=false,Impression=false,ListeCouleurs={Tomato,LightSteelBlue,LightGreen,Cornsilk}}%
+
+\newcommand\RepresenterEntier[2][]{%
+ \useKVdefault[ClesREntier]%
+ \setKV[ClesREntier]{#1}%
+ \ifboolKV[ClesREntier]{Unite}{%
+ \begin{Geometrie}[TypeTrace="Espace",CoinBG={u*(-10,-10)}]
+ Echelle=\useKV[ClesREntier]{Echelle};
+ Initialisation(5,30,15,50*Echelle);
+ color A,B,C,D,E,F,G,H;
+ pointilles:="non";
+ trace Pave(A,B,C,D,E,F,G,H)(0.1,0.1,0.1);
+ \end{Geometrie}
+ }{%
+ % On décompose le nombre
+ \StrLen{#2}[\LongueurNombreEntier]%
+ \xdef\FooListeEntier{}
+ \xintFor* ##1 in{\xintSeq{1}{\LongueurNombreEntier}}\do{%
+ \StrChar{#2}{##1}[\ChiffreAAjouter]
+ \xdef\FooListeEntier{\FooListeEntier \ChiffreAAjouter,}
+ }
+ \setsepchar{,}\ignoreemptyitems
+ \readlist*\ListeDesChiffres{\FooListeEntier}%
+ \xdef\ListeAvantCouleurs{\useKV[ClesREntier]{ListeCouleurs}}%
+ \readlist*\ListeCouleurEntier{\ListeAvantCouleurs}%
+ \xintifboolexpr{\LongueurNombreEntier==4}{%
+ \xdef\NombreMilliers{\ListeDesChiffres[1]}%
+ \xdef\NombreCentaines{\ListeDesChiffres[2]}%
+ \xdef\NombreDizaines{\ListeDesChiffres[3]}%
+ \xdef\NombreUnites{\ListeDesChiffres[4]}%
+ }{%
+ \xintifboolexpr{\LongueurNombreEntier==3}{%
+ \xdef\NombreMilliers{0}%
+ \xdef\NombreCentaines{\ListeDesChiffres[1]}%
+ \xdef\NombreDizaines{\ListeDesChiffres[2]}%
+ \xdef\NombreUnites{\ListeDesChiffres[3]}%
+ }{%
+ \xintifboolexpr{\LongueurNombreEntier==2}{%
+ \xdef\NombreMilliers{0}%
+ \xdef\NombreCentaines{0}%
+ \xdef\NombreDizaines{\ListeDesChiffres[1]}%
+ \xdef\NombreUnites{\ListeDesChiffres[2]}%
+ }{%
+ \xdef\NombreMilliers{0}%
+ \xdef\NombreCentaines{0}%
+ \xdef\NombreDizaines{0}%
+ \xdef\NombreUnites{\ListeDesChiffres[1]}%
+ }%
+ }%
+ }%
+ \begin{Geometrie}[TypeTrace="Espace",CoinBG={u*(-10,-10)},CoinHD={u*(20,20)}]
+ Echelle=\useKV[ClesREntier]{Echelle};
+ NM=\NombreMilliers;
+ NC=\NombreCentaines;
+ ND=\NombreDizaines;
+ NU=\NombreUnites;
+ color ColorEntier[];
+ ColorEntier1=\ListeCouleurEntier[1];
+ ColorEntier2=\ListeCouleurEntier[2];
+ ColorEntier3=\ListeCouleurEntier[3];
+ ColorEntier4=\ListeCouleurEntier[4];
+ boolean Compact,Print;
+ Compact=\useKV[ClesREntier]{Compact};
+ Print=\useKV[ClesREntier]{Impression};
+ Initialisation(5,30,15,50*Echelle);
+ color A,B,C,D,E,F,G,H;
+ picture TypePave[];
+ TypePave0=image(
+ trace Pave(A,B,C,D,E,F,G,H)(1,1,1);
+ currentpicture:=nullpicture;
+ remplis polygone(A,B,C,H,E,F) withcolor if Print : blanc else: ColorEntier1 fi;
+ for k=0 upto 10:
+ trace chemin((k/10)[A,B],(k/10)[F,G],(k/10)[E,H]);
+ endfor;
+ for k=0 upto 10:
+ trace chemin((k/10)[B,C],(k/10)[G,H],(k/10)[F,E]);
+ endfor;
+ for k=0 upto 10:
+ trace chemin((k/10)[A,F],(k/10)[B,G],(k/10)[C,H]);
+ endfor;
+ %if Compact:
+ %trace chemin(B,B+(0,0,-0.2)) dashed evenly withpen pencircle scaled 1.25;
+ %fi;
+ );
+ color A,B,C,D,E,F,G,H;
+ TypePave1=image(
+ trace Pave(A,B,C,D,E,F,G,H)(0.1,1,1);
+ currentpicture:=nullpicture;
+ remplis polygone(A,B,C,H,E,F) withcolor if Print : blanc else: ColorEntier2 fi;
+ trace chemin(C,H,E);
+ for k=0 upto 10:
+ trace chemin((k/10)[A,B],(k/10)[F,G],(k/10)[E,H]);
+ endfor;
+ for k=0 upto 10:
+ trace chemin((k/10)[A,F],(k/10)[B,G],(k/10)[C,H]);
+ endfor;
+ %if Compact:
+ %trace chemin(B,B+(0,0,-0.2)) dashed evenly withpen pencircle scaled 1.25;
+ %fi;
+ );
+ color A,B,C,D,E,F,G,H;
+ TypePave2=image(
+ trace Pave(A,B,C,D,E,F,G,H)(0.1,0.1,1);
+ currentpicture:=nullpicture;
+ remplis polygone(A,B,C,H,E,F) withcolor if Print : blanc else: ColorEntier3 fi;
+ trace chemin(C,H,E);
+ trace chemin(A,F,E);
+ trace chemin(B,G,F);
+ for k=0 upto 10:
+ trace chemin((k/10)[A,F],(k/10)[B,G],(k/10)[C,H]);
+ endfor;
+ %if Compact:
+ %trace chemin(B,B+(0,0,-0.2)) dashed evenly withpen pencircle scaled 1.25;
+ %fi;
+ );
+ color A,B,C,D,E,F,G,H;
+ TypePave3=image(
+ trace Pave(A,B,C,D,E,F,G,H)(0.1,0.1,0.1);
+ currentpicture:=nullpicture;
+ remplis polygone(A,B,C,H,E,F) withcolor if Print : blanc else: ColorEntier4 fi;
+ trace chemin(C,H,E);
+ trace chemin(A,F,E);
+ trace chemin(A,B,C);
+ trace chemin(F,G,H);
+ trace chemin(B,G);
+ );
+ if Compact:
+ for k=0 upto (\NombreMilliers-1):
+ trace TypePave0 shifted ((Projette((k,0,0))-Projette((0,0,0))));
+ endfor;
+ for k=0 upto (\NombreCentaines-1):
+ trace TypePave1 shifted ((Projette((0.1*k,1.5,0))-Projette((0,0,0))));
+ endfor;
+ for k=0 upto (\NombreDizaines-1):
+ trace TypePave2 shifted ((Projette((0.1*k,3,0))-Projette((0,0,0))));
+ endfor;
+ for k=0 upto (\NombreUnites-1):
+ trace TypePave3 shifted ((Projette((0,3.6,0.1*k))-Projette((0,0,0))));
+ endfor;
+ else:
+ for k=0 upto (\NombreMilliers-1):
+ trace TypePave0 shifted ((Projette((0,1.1*(k-1),0))-Projette((0,0,0))));
+ endfor;
+ for k=0 upto (\NombreCentaines-1):
+ trace TypePave1 shifted ((Projette((0,1.1*\NombreMilliers+1.1*(k-1),0))-Projette((0,0,0))));
+ endfor;
+ for k=0 upto (\NombreDizaines-1):
+ trace TypePave2 shifted ((Projette((0,1.1*\NombreMilliers+1.1*(\NombreCentaines-1)+0.2+0.2*(k-1),0))-Projette((0,0,0))));
+ endfor;
+ for k=0 upto (\NombreUnites-1):
+ trace TypePave3 shifted ((Projette((0,1.1*\NombreMilliers+1.1*(\NombreCentaines-1)+0.2+0.2*(\NombreDizaines-1),0.2*(k)))-Projette((0,0,0))));
+ endfor;
+ fi;
+ \end{Geometrie}
+ }
+}
+
+% Gestion de l'aléatoire (pour la CAN)
+\newcommand\ChoixAlea[4][]{%
+ \ifx\bla#1\bla%
+ \xdef#4{\fpeval{randint(#2,#3)}}%
+ \else%
+ \xdef#4{\fpeval{round(randint(#2,#3)+rand(),#1)}}%
+ \fi%
+}%
+
+\def\VariableAlea#1#2{%
+ \xdef#1{\fpeval{#2}}%
+}%
+
+% On bloque la graine de fabrication des nombres aléatoires.
+\ExplSyntaxOn
+\cs_new_eq:NN \PfCGraineAlea \sys_gset_rand_seed:n
+\ExplSyntaxOff
+
+%%%
+% Course aux nombres
+%%%
+\RequirePackage{longtable}
+% https://tex.stackexchange.com/questions/642775/when-displaying-a-datatool-database-with-dtldisplaylongdb-how-to-obtain-a-hor
+% Patch éventuel à ajouter
+%\makeatletter
+%\expandafter\patchcmd\expandafter{\csname\string\DTLdisplaylongdb\endcsname}%
+% {\@dtl@resetdoamp\dtldisplaystarttab}%
+% {\dtldisplaystarttab\@dtl@resetdoamp}%
+% {\message{Patching succeeded.}}%
+% {\message{Patching failed.}}%
+%\makeatother
+
+\setKVdefault[ClesMathAlea]{NbQ=5,ChoixTables=2-9,ValeurMax=20,Classique,Trou=false,Melange=false,Multiple=2,Theme=false}%
+\defKV[ClesMathAlea]{Trous=\setKV[ClesMathAlea]{Classique=false}\setKV[ClesMathAlea]{Trou}}%
+\defKV[ClesMathAlea]{Melanges=\setKV[ClesMathAlea]{Classique=false}\setKV[ClesMathAlea]{Melange}}%
+
+\newcommand\MathAlea[2][]{%
+ \useKVdefault[ClesMathAlea]%
+ \setKV[ClesMathAlea]{#1}%
+ \input{#2}%
+}%
+
+\newcommand\CourseNombreTotalQuestions[1]{%
+ \setKV[ClesCN]{TotalQ=#1}%
+ \xdef\CNfoo{}%
+ \xintFor* ##1 in{\xintSeq{1}{#1}}\do{%
+ \xdef\CNfoo{\CNfoo ##1,}%
+ }%
+}%
+
+\setKVdefault[ClesCN]{%
+ Stretch=2.5,%Elasticité du tableau
+ NbQ=5,%Nb de questions à poser
+ RAZ=false,%Pour remettre à zéro le compteur des questions
+ Ordre=false,%Pour mettre toutes les questions dans l'ordre des numéros
+ Exercice=false,%Pour utiliser l'aléatoire des questions mais sans habillage particulier, autre que des \item
+ Perso=false,%Pour que utiliser un choix personnel des questions
+ Lecture=false,%Pour différencier avec une lecture automatisée sur les numéros de fichiers
+ Maitre=false,%Pour indiquer qu'on prend en compte ou pas les sous-dossiers
+ Nom=false,%Pour afficher le nom des fichiers utilisés.
+ Theme=false,%Pour afficher le theme travaillé dans les fichiers utilisés.
+ AMC=false,%
+ Multi=false%
+}%
+\defKV[ClesCN]{Liste=\setKV[ClesCN]{Perso=true}\setKV[ClesCN]{Lecture}}%
+\defKV[ClesCN]{Dossier=\setKV[ClesCN]{Lecture}}%
+\defKV[ClesCN]{Debut=\setKV[ClesCN]{RAZ}}%
+\setsepchar[*]{,*/}%
+\readlist*\ListeMotsCAN{La moitié de /2,Le double de /1,Le triple de /1, Le tiers de /3,Le nombre dix fois plus grand que /1,Le nombre cent fois plus grand que /1,Le nombre mille fois plus grand que /1,Le nombre dix fois plus petit que /10,Le nombre cent fois plus petit que /100,Le nombre mille fois plus petit que /1000}%
+\readlist*\ListeMulAstucieuxCAN{50/2,25/4,20/5}%
+\readlist*\ListeLieuxObjetsCAN{boulangerie/pains au chocolat/un pain au chocolat,boulangerie/cookies/un cookie,boulangerie/brioches/une brioche,piscine/entrées/une entrée,boucherie/saucisses/une saucisse,boucherie/cuisses de poulet/une cuisse de poulet}%
+\readlist*\ListeNomsCAN{Aude/Elle,Bernard/Il,Céline/Elle,Daniel/Il,Elise/Elle,Fabien/Il,Gérard/Il,Hélène/Elle,Ilies/Il,Jasmine/Elle,Kylian/Il,Laurent/Il,Mathilde/Elle,Nina/Elle,Octave/Il,Philippe/Il,Joachim/Il,Thérèse/Elle,Nawel/Elle,Alexandre/Il,Maxence/Il,Sophie/Elle,Christophe/Il,Myriam/Elle}%
+\readlist*\ListeComposantStatCAN{voitures/un garage/Cross-over/Utilitaires/Berlines,fruits/une corbeille/Pommes/Oranges/Bananes,vêtements/une armoire/Pulls/T-shirts/Chemises,couverts/un tiroir/Fourchettes/Couteaux/Cuillères}%
+\readlist*\ListeObjetsSymbolesCAN{fleurs/96,ciseaux/36,crayons/47,enveloppes/41}%uniquement avec pifont
+\setsepchar{,}%
+\readlist*\ListeObjetsCAN{bonbons,billes,jouets,fruits,biscuits,gâteaux,pommes,poires}
+\readlist*\ListeFruitsCAN{pommes,poires,abricots,cerises,fraises,framboises,noix,pêches,nectarines,myrtilles}
+\readlist*\ListeSommetsCAN{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}
+
+\newcommand\ExtraitSymboles[1]{%
+ \xdef\CANSGFoo{}%
+ \foreachitem\compteur\in\ListeObjetsSymbolesCAN{%
+ \xdef\CANSGFoo{\CANSGFoo \ListeObjetsSymbolesCAN[\compteurcnt],}%
+ }%
+ \MelangeListe{\CANSGFoo}{#1}%
+ \setsepchar[*]{,*/}%
+ \readlist*\SymbolesMelanges{\faa}%
+ \setsepchar{,}%
+}%
+
+\newcommand\ExtraitSommet[1]{%
+ \xdef\CANSGFoo{}%
+ \foreachitem\compteur\in\ListeSommetsCAN{%
+ \xdef\CANSGFoo{\CANSGFoo \ListeSommetsCAN[\compteurcnt],}%
+ }%
+ \MelangeListe{\CANSGFoo}{#1}%
+ \readlist*\SommetsMelanges{\faa}%
+}%
+
+\newcommand\ExtraitFruit[1]{%
+ \xdef\CANSGFoo{}%
+ \foreachitem\compteur\in\ListeFruitsCAN{%
+ \xdef\CANSGFoo{\CANSGFoo \ListeFruitsCAN[\compteurcnt],}%
+ }%
+ \MelangeListe{\CANSGFoo}{#1}%
+ \readlist*\FruitsMelanges{\faa}%
+}%
+
+\newcommand\ExtraitNom[1]{%
+ \xdef\CANSGFoo{}%
+ \foreachitem\compteur\in\ListeNomsCAN{%
+ \xdef\CANSGFoo{\CANSGFoo \ListeNomsCAN[\compteurcnt],}%
+ }%
+ \MelangeListe{\CANSGFoo}{#1}%
+ \setsepchar[*]{,*/}%
+ \readlist*\NomsMelanges{\faa}%
+ \setsepchar{,}%
+}%
+
+\newcommand\ExtraitElements[1]{%
+ \xdef\CANSGFoo{}%
+ \foreachitem\compteur\in\ListeComposantStatCAN{%
+ \xdef\CANSGFoo{\CANSGFoo \ListeComposantStatCAN[\compteurcnt],}%
+ }%
+ \MelangeListe{\CANSGFoo}{#1}%
+ \setsepchar[*]{,*/}%
+ \readlist*\ElementsMelanges{\faa}%
+ \setsepchar{,}%
+}%
+
+\newcounter{CNNumQ}%
+\setcounter{CNNumQ}{1}%
+
+\newcommand\CANNew{%
+ \textcolor{Crimson}{\faCopy}%
+}%
+
+\newread\RecupNbFichiers
+\newread\RecupSSDossiers
+\newread\zzz
+\def\zzpar{\par}%
+
+\makeatletter
+\def\app@exe{\write18}
+% Recuperer les sous-dossiers
+\def\RecupererSousDossiers#1{%#1 est le dossier contenant les fichiers can classés en sous-dossier
+ \app@exe{rm -f RecapSSDossier.tmp ; ls -1 -I "*.tex" #1 > RecapSSDossier.tmp}%
+ \immediate\openin\zzz=RecapSSDossier.tmp
+ \loop%
+ \read\zzz to \tmp%
+ \ifx\tmp\zzpar\else%
+ \xdef\CNFOOSSDossiers{\CNFOOSSDossiers \expandafter\detokenize\expandafter{\tmp},}%
+ \fi%
+ \ifeof\zzz\else%
+ \repeat%
+ \setsepchar{,}\ignoreemptyitems
+ \readlist*\ListeSSDossiers{\CNFOOSSDossiers}
+}
+
+\def\RecupererFichierTeXSSDossier#1#2{%
+ \openin\zzz="|ls #1/#2/*.tex"%
+ \loop%
+ \read\zzz to \tmp%
+ \ifx\tmp\zzpar\else%
+ \xdef\CNFOO{\CNFOO \expandafter\detokenize\expandafter{\tmp},}%
+ \fi%
+ \ifeof\zzz\else%
+ \repeat%
+}
+
+\def\RecupererFichierTeXDossier#1{%
+ \xdef\CNFOO{}%
+ \openin\zzz="|ls #1/*.tex"
+ \loop%
+ \read\zzz to \tmp%
+ \ifx\tmp\zzpar\else%
+ \xdef\CNFOO{\CNFOO \expandafter\detokenize\expandafter{\tmp},}%
+ \fi%
+ \ifeof\zzz\else%
+ \repeat%
+}
+
+\def\DefinirListeFichiers{%
+ \setsepchar{,}\ignoreemptyitems%
+ \readlist*\ListeFichiers{\CNFOO}%
+}
+
+\def\RecupererFichierTeXAllSSDossier#1{%
+ \RecupererSousDossiers{#1}%
+ \foreachitem\compteur\in\ListeSSDossiers{\RecupererFichierTeXSSDossier{#1}{\ListeSSDossiers[\compteurcnt]}}%
+ \DefinirListeFichiers%
+}
+
+\def\RecupererFichierTeXAllDossier#1{%
+ \RecupererFichierTeXDossier{#1}%
+ \DefinirListeFichiers%
+}
+
+\def\RecupererFichierTeXComplet#1{%
+ \RecupererFichierTeXDossier{#1}%
+ \RecupererSousDossiers{#1}%
+ \foreachitem\compteur\in\ListeSSDossiers{\RecupererFichierTeXSSDossier{#1}{\ListeSSDossiers[\compteurcnt]}}%
+ \DefinirListeFichiers%
+}
+
+\def\RecupererFichierTeXSSDossierPerso#1{%
+ \openin\zzz="|ls #1/*.tex"
+ \loop%
+ \read\zzz to \tmp%
+ \ifx\tmp\zzpar\else%
+ \xdef\CNFOO{\CNFOO \expandafter\detokenize\expandafter{\tmp},}%
+ \fi%
+ \ifeof\zzz\else%
+ \repeat%
+}
+
+\makeatother
+
+\newcommand\CNTheme[1]{}%
+
+\NewDocumentCommand\CourseNombre{o m}{%
+ \setKV[ClesMathAlea]{NbQ=1}%
+ \useKVdefault[ClesCN]%
+ \setKV[ClesCN]{#1}%
+ \ifboolKV[ClesCN]{Theme}{\renewcommand\CNTheme[1]{{\ttfamily Thème : ##1}\par}}{}%
+ \ifboolKV[ClesCN]{RAZ}{%\setcounter{CNNumQ}{1}}{}%
+ \setcounter{CNNumQ}{\useKV[ClesCN]{Debut}}%
+ }{}%
+ \setKV[ClesMathAlea]{NbQ=1}%
+ \xdef\CNFOOSSDossiers{}%
+ \xdef\CNFOO{}%
+ \ifboolKV[ClesCN]{Lecture}{%
+ \ifboolKV[ClesCN]{Perso}{%
+ % % Ici \useKV[ClesCN]{Liste}
+ \xdef\CNFOOListePerso{\useKV[ClesCN]{Liste}}%
+ % % OK -> Là, normalement, c'est la liste des dossiers choisis par l'utilisateur : \CNFOOListePerso
+ \setsepchar{,}%
+ \readlist*\ListeDesSSDossiersPerso{\CNFOOListePerso}%
+ % % \par OK -> Là, normalement, c'est la liste des dossiers perso sous forme de liste : \showitems\ListeDesSSDossiersPerso[]%
+ \foreachitem\compteur\in\ListeDesSSDossiersPerso{\RecupererFichierTeXSSDossierPerso{\ListeDesSSDossiersPerso[\compteurcnt]}}%
+ \DefinirListeFichiers%
+ % % \par OK -> Là, enfin, normalement, c'est la liste des fichiers contenus dans les dossiers perso :
+ % % \showitems\ListeFichiers[]
+ }{%
+ \ifboolKV[ClesCN]{Maitre}{%
+ % % On récupère tous les fichiers can dans les sous-dossiers
+ % % et on construit une liste \ListeFichiers contenant les chemins des fichiers considérés.
+ \RecupererFichierTeXComplet{\useKV[ClesCN]{Dossier}}%
+ }{%
+ % % Là
+ % % On récupère seulement les fichiers can de ce dossier
+ % % et on consruit une liste \ListeFichiers contenant les chemins des fichiers considérés.
+ \RecupererFichierTeXAllDossier{\useKV[ClesCN]{Dossier}}%
+ }%
+ }%
+ % % On crée la liste du nombre total de questions
+ \xdef\CNfooListe{}%
+ \xintFor* ##1 in{\xintSeq{1}{\ListeFichierslen}}\do{%
+ \xdef\CNfooListe{\CNfooListe ##1,}%
+ }%
+ % % \par OK -> normalement, on a la liste du nombre de questions : \CNfooListe
+ % % On affiche les questions :
+ \ifboolKV[ClesCN]{Ordre}{%
+ % % soit dans un exercice
+ \ifboolKV[ClesCN]{Exercice}{%
+ % % Attention le style de l'environnement est à choisir par l'utilisateur
+ \xintFor* ##1 in {\xintSeq{1}{\ListeFichierslen}}\do{%
+ \item\input{\ListeFichiers[##1]}%
+ }%
+ }{% Soit toutes les questions au format course
+ \renewcommand{\arraystretch}{\useKV[ClesCN]{Stretch}}%
+ \begin{longtable}{|c|p{0.7\linewidth}|p{0.1\linewidth}|p{0.05\linewidth}|}%
+ \hhline{~---}%
+ \multicolumn{1}{c|}{}&\cellcolor{gray!15}\centering\'Enoncé&\cellcolor{gray!15}\centering Réponse&\cellcolor{gray!15}\centering\arraybackslash Jury\\%
+ \hline%
+ \endhead%
+ \xintFor* ##1 in {\xintSeq{1}{\ListeFichierslen}}\do{%
+ \ttfamily{\theCNNumQ}\stepcounter{CNNumQ}&\input{\ListeFichiers[##1]}\ifboolKV[ClesCN]{Nom}{\par\hfill\footnotesize\ttfamily\ListeFichiers[##1]}{}&&\\%
+ \hline%
+ }%
+ \end{longtable}%
+ \renewcommand{\arraystretch}{1}%
+ }%
+ }{%
+ % On prévient l'utilisateur si le nb de questions est inférieur à NbQ
+ \xintifboolexpr{\ListeFichierslen<\useKV[ClesCN]{NbQ}}{%
+ \faExclamationCircle~Le nombre maximal de questions est inférieur au nombre de questions à afficher. Modifier la clé {\ttfamily NbQ} ou ajouter des questions dans le(s) répertoire(s).%
+ }{%%On choisit NbQ questions parmi la liste de fichiers
+ \MelangeListe{\CNfooListe}{\useKV[ClesCN]{NbQ}}%
+ \setsepchar{,}\ignoreemptyitems%
+ \readlist*\ListeCNQuestions{\faa}
+ \ifboolKV[ClesCN]{Exercice}{%
+ \xintFor* ##1 in {\xintSeq{1}{\useKV[ClesCN]{NbQ}}}\do{%
+ \item\xdef\Numerodelaquestionaposer{\ListeCNQuestions[##1]}\input{\ListeFichiers[\Numerodelaquestionaposer]}%
+ }%
+ }{% On les affiche
+ \renewcommand{\arraystretch}{\useKV[ClesCN]{Stretch}}%
+ \begin{longtable}{|c|p{0.7\linewidth}|p{0.1\linewidth}|p{0.05\linewidth}|}%
+ \hhline{~---}%
+ \multicolumn{1}{c|}{}&\cellcolor{gray!15}\centering\'Enoncé&\cellcolor{gray!15}\centering Réponse&\cellcolor{gray!15}\centering\arraybackslash Jury\\%
+ \hline%
+ \endhead%
+ \xintFor* ##1 in {\xintSeq{1}{\useKV[ClesCN]{NbQ}}}\do{%
+ \ttfamily{\theCNNumQ}\stepcounter{CNNumQ}&\xdef\Numerodelaquestionaposer{\ListeCNQuestions[##1]}\input{\ListeFichiers[\Numerodelaquestionaposer]}\ifboolKV[ClesCN]{Nom}{\par\hfill\footnotesize\ttfamily\ListeFichiers[##1]}{}&&\\
+ \hline
+ }%
+ \end{longtable}%
+ \renewcommand{\arraystretch}{1}%
+ }%
+ }%
+ }%
+ }{%
+ \input{#2}
+ }%
+}%
+% fin course aux nombres
+
+%%%
+% Frise temporelle
+%%%
+\setKVdefault[ClesFrise]{Longueur=8cm,Fleches=false,Ecart=5mm,Sup=false}%
+
+\newtoks\toklistefrise%
+\def\UpdatetoksFrise#1/#2/#3\nil{\addtotok\toklistefrise{"#1","#2","#3",}}%
+
+\newcommand\Frise[2][]{%
+ \useKVdefault[ClesFrise]%
+ \setKV[ClesFrise]{#1}%
+ \setsepchar[*]{,*/}\ignoreemptyitems%
+ \readlist*\ListeTempo{#2}%
+ \toklistefrise{}%
+ \foreachitem\compteur\in\ListeTempo{\expandafter\UpdatetoksFrise\compteur\nil}
+ \MPDessineFrise{\the\toklistefrise}%
+}
+
+\newcommand\MPDessineFrise[1]{%
+ \ifluatex
+ \mplibforcehmode
+ \begin{mplibcode}
+ Longueur:=\useKV[ClesFrise]{Longueur};
+ Ecart:=\useKV[ClesFrise]{Ecart};
+ boolean Fleches;
+ Fleches=\useKV[ClesFrise]{Fleches};
+ boolean Sup;
+ Sup=\useKV[ClesFrise]{Sup};
+ pair A[],B;
+ A0=(0,0);
+ B-A0=(Longueur,0);
+ n=0;
+ for p_=#1:
+ n:=n+1;
+ endfor;
+ for k=1 upto ((n div 3)-2):
+ A[k]=(k/((n div 3)-1))[A0,B];
+ endfor;
+ A[(n div 3)-1]=B;
+ if Sup:
+ for k=0 upto ((n div 3)-1):
+ trace (u*(0,-0.1)--u*(0,0.1)) shifted A[k];
+ endfor;
+ % on définit les points milieu des fleches
+ path Fleche[];
+ pair C[];
+ for k=0 upto ((n div 3)-3):
+ Fleche[k]=(A[k]{dir-30}..{dir30}A[k+1]) shifted((0,-Ecart));
+ C[k]=point (0.5*length Fleche[k]) of Fleche[k];
+ endfor;
+ Fleche[(n div 3)-2]=%(A[(n div 3)-3]{dir-30}..{dir30}A[(n div 3)-1]) shifted((0,-Ecart));
+ chemin(A[(n div 3)-3]+(0,-Ecart),A[(n div 3)-3]+(0,-4*Ecart),A[(n div 3)-1]+(0,-4*Ecart),A[(n div 3)-1]+(0,-Ecart));
+ C[(n div 3)-1]=point (0.5*length Fleche[(n div 3)-2]) of Fleche[(n div 3)-2];
+ Fleche[(n div 3)-1]=(A[(n div 3)-1]{dir-150}..{dir150}A[(n div 3)-2]) shifted((0,-Ecart));
+ C[(n div 3)-2]=point (0.5*length Fleche[(n div 3)-1]) of Fleche[(n div 3)-1];
+ %
+ maxx:=n;
+ trace segment(A0,A[(n div 3)-2]);
+ trace segment(A[(n div 3)-2],A[(n div 3)-1]) dashed evenly;
+ n:=0;
+ labeloffset:=labeloffset*2;
+ for p_=#1:
+ n:=n+1;
+ if n<maxx+1:
+ if (n mod 3)=1:
+ label.top(TEX(""&p_&""),A[n div 3]);
+ elseif (n mod 3)=2:
+ label.top(TEX(""&p_&""),C[n div 3]);%
+ elseif (n mod 3)=0:
+ label.bot(TEX(""&p_&""),C[(n div 3)-1]);
+ fi;
+ fi;
+ endfor;
+ drawoptions();
+ labeloffset:=labeloffset/2;
+ if Fleches:
+ for k=0 upto ((n div 3)-4):
+ drawarrow Fleche[k];
+ endfor;
+ drawarrow Fleche[(n div 3)-1];
+ drawarrow Fleche[(n div 3)-2];
+ drawarrow (A[(n div 3)-1]{dir-150}..{dir150}A[(n div 3)-2]) shifted((0,-Ecart));
+ for k=0 upto ((n div 3)-2):
+ draw segment(A[k],A[k]+(0,-Ecart)) dashed evenly;
+ endfor;
+ draw segment(A[(n div 3)-1],A[(n div 3)-1]+(0,-Ecart)) dashed evenly;
+ fi;
+ %fin Sup
+ else:
+ for k=0 upto ((n div 3)-1):
+ trace (u*(0,-0.1)--u*(0,0.1)) shifted A[k];
+ endfor;
+ % on définit les points milieu des fleches
+ path Fleche[];
+ pair C[];
+ for k=0 upto ((n div 3)-2):
+ Fleche[k]=(A[k]{dir-30}..{dir30}A[k+1]) shifted((0,-Ecart));
+ C[k]=point (0.5*length Fleche[k]) of Fleche[k];
+ endfor;
+ maxx:=n;
+ trace segment(A0,A[(n div 3)-1]);
+ n:=0;
+ labeloffset:=labeloffset*2;
+ for p_=#1:
+ n:=n+1;
+ if n<maxx:
+ if (n mod 3)=1:
+ label.top(TEX(""&p_&""),A[n div 3]);
+ elseif (n mod 3)=2:
+ if (n div 3)<((maxx div 3)-1):label.top(TEX(""&p_&""),C[n div 3]);fi;
+ elseif (n mod 3)=0:
+ label.bot(TEX(""&p_&""),C[(n div 3)-1]);
+ fi;
+ fi;
+ endfor;
+ labeloffset:=labeloffset/2;
+ if Fleches:
+ for k=0 upto ((n div 3)-2):
+ draw segment(A[k],A[k]+(0,-Ecart)) dashed evenly;
+ drawarrow Fleche[k];
+ endfor;
+ draw segment(A[(n div 3)-1],A[(n div 3)-1]+(0,-Ecart)) dashed evenly;
+ fi;
+ fi;
+ \end{mplibcode}
+ \else
+ \begin{mpost}[mpsettings={%
+ Longueur:=\useKV[ClesFrise]{Longueur};
+ Ecart:=\useKV[ClesFrise]{Ecart};
+ boolean Fleches;
+ Fleches=\useKV[ClesFrise]{Fleches};
+ boolean Sup;
+ Sup=\useKV[ClesFrise]{Sup};
+ }]
+ pair A[],B;
+ A0=(0,0);
+ B-A0=(Longueur,0);
+ n=0;
+ for p_=#1:
+ n:=n+1;
+ endfor;
+ for k=1 upto ((n div 3)-2):
+ A[k]=(k/((n div 3)-1))[A0,B];
+ endfor;
+ A[(n div 3)-1]=B;
+ if Sup:
+ for k=0 upto ((n div 3)-1):
+ trace (u*(0,-0.1)--u*(0,0.1)) shifted A[k];
+ endfor;
+ % on définit les points milieu des fleches
+ path Fleche[];
+ pair C[];
+ for k=0 upto ((n div 3)-3):
+ Fleche[k]=(A[k]{dir-30}..{dir30}A[k+1]) shifted((0,-Ecart));
+ C[k]=point (0.5*length Fleche[k]) of Fleche[k];
+ endfor;
+ Fleche[(n div 3)-2]=%(A[(n div 3)-3]{dir-30}..{dir30}A[(n div 3)-1]) shifted((0,-Ecart));
+ chemin(A[(n div 3)-3]+(0,-Ecart),A[(n div 3)-3]+(0,-4*Ecart),A[(n div 3)-1]+(0,-4*Ecart),A[(n div 3)-1]+(0,-Ecart));
+ C[(n div 3)-1]=point (0.5*length Fleche[(n div 3)-2]) of Fleche[(n div 3)-2];
+ Fleche[(n div 3)-1]=(A[(n div 3)-1]{dir-150}..{dir150}A[(n div 3)-2]) shifted((0,-Ecart));
+ C[(n div 3)-2]=point (0.5*length Fleche[(n div 3)-1]) of Fleche[(n div 3)-1];
+ %
+ maxx:=n;
+ trace segment(A0,A[(n div 3)-2]);
+ trace segment(A[(n div 3)-2],A[(n div 3)-1]) dashed evenly;
+ n:=0;
+ labeloffset:=labeloffset*2;
+ for p_=#1:
+ n:=n+1;
+ if n<maxx+1:
+ if (n mod 3)=1:
+ label.top(LATEX(""&p_&""),A[n div 3]);
+ elseif (n mod 3)=2:
+ label.top(LATEX(""&p_&""),C[n div 3]);%
+ elseif (n mod 3)=0:
+ label.bot(LATEX(""&p_&""),C[(n div 3)-1]);
+ fi;
+ fi;
+ endfor;
+ drawoptions();
+ labeloffset:=labeloffset/2;
+ if Fleches:
+ for k=0 upto ((n div 3)-4):
+ drawarrow Fleche[k];
+ endfor;
+ drawarrow Fleche[(n div 3)-1];
+ drawarrow Fleche[(n div 3)-2];
+ drawarrow (A[(n div 3)-1]{dir-150}..{dir150}A[(n div 3)-2]) shifted((0,-Ecart));
+ for k=0 upto ((n div 3)-2):
+ draw segment(A[k],A[k]+(0,-Ecart)) dashed evenly;
+ endfor;
+ draw segment(A[(n div 3)-1],A[(n div 3)-1]+(0,-Ecart)) dashed evenly;
+ fi;
+ %fin Sup
+ else:
+ for k=0 upto ((n div 3)-1):
+ trace (u*(0,-0.1)--u*(0,0.1)) shifted A[k];
+ endfor;
+ % on définit les points milieu des fleches
+ path Fleche[];
+ pair C[];
+ for k=0 upto ((n div 3)-2):
+ Fleche[k]=(A[k]{dir-30}..{dir30}A[k+1]) shifted((0,-Ecart));
+ C[k]=point (0.5*length Fleche[k]) of Fleche[k];
+ endfor;
+ maxx:=n;
+ trace segment(A0,A[(n div 3)-1]);
+ n:=0;
+ labeloffset:=labeloffset*2;
+ for p_=#1:
+ n:=n+1;
+ if n<maxx:
+ if (n mod 3)=1:
+ label.top(LATEX(""&p_&""),A[n div 3]);
+ elseif (n mod 3)=2:
+ if (n div 3)<((maxx div 3)-1):label.top(LATEX(""&p_&""),C[n div 3]);fi;
+ elseif (n mod 3)=0:
+ label.bot(LATEX(""&p_&""),C[(n div 3)-1]);
+ fi;
+ fi;
+ endfor;
+ labeloffset:=labeloffset/2;
+ if Fleches:
+ for k=0 upto ((n div 3)-2):
+ draw segment(A[k],A[k]+(0,-Ecart)) dashed evenly;
+ drawarrow Fleche[k];
+ endfor;
+ draw segment(A[(n div 3)-1],A[(n div 3)-1]+(0,-Ecart)) dashed evenly;
+ fi;
+ fi;
+ \end{mpost}
+ \fi
+}
+
+%%%
% Geometrie
%%%
\setKVdefault[Geometrie]{CoinBG={(0,0)},CoinHD={(10u,10u)},TypeTrace="Instruments"}%
@@ -404,7 +1116,7 @@
%%https://tex.stackexchange.com/questions/3695/smileys-in-latex/227226
\tikzset{face/.style={shape=circle,minimum size=4ex,shading=radial,outer sep=0pt, inner color=white!50!yellow,outer color= yellow!70!orange}}
-\newcommand{\emoticon}[2][]{%
+\newcommand\emoticon[2][]{%
\scalebox{.5}{\begin{tikzpicture}
\node[face,#1,draw,thick] (emoticon) {};
%% The eyes are fixed.
@@ -413,7 +1125,7 @@
\end{tikzpicture}}%
}
-\newcommand{\pupils}{
+\newcommand\pupils{
%% standard pupils
\fill[shift={(0.5ex,0.5ex)},rotate=80] (0,0) ellipse (0.3ex and 0.15ex);
\fill[shift={(-0.5ex,0.5ex)},rotate=100] (0,0) ellipse (0.3ex and 0.15ex);}
@@ -614,8 +1326,8 @@
\newcommand\MelangeListe[2]{%
% #1 Liste à mélanger
% #2 Nombre d'éléments à conserver
- \setsepchar{,}\ignoreemptyitems
- \readlist*\ListeInter{#1}
+ \setsepchar{,}\ignoreemptyitems%
+ \readlist*\ListeInter{#1}%
\xdef\faa{}% Liste construite
\xdef\fii{}% Liste détruite
% on crée les #2 premieres solutions.
@@ -1112,7 +1824,7 @@
\xdef\CountcolDeux{0}%
\useKVdefault[ClesFicheMemo]%
\setKV[ClesFicheMemo]{#1}%
- \setsepchar[*]{§*/}%
+ \setsepchar[*]{§*/}\reademptyitems%
\readlist*\ListeQuestionColonneUn{#2}%
\readlist*\ListeQuestionColonneDeux{#3}%
\renewcommand{\arraystretch}{1.35}%
@@ -1123,35 +1835,36 @@
\tikz\draw[dashed,gray!50](2-|4.5) to (last-|4.5);%
\Body%
\Block{1-1}{\bfseries\useKV[ClesFicheMemo]{TexteReponses}}&&&\Block{1-1}{\bfseries\useKV[ClesFicheMemo]{TexteReponses}}\\
- \xintFor* ##4 in {\xintSeq {1}{\ListeQuestionColonneUnlen}}\do{%
- \xintifboolexpr{\listlen\ListeQuestionColonneUn[##4]==2}{%
+ \xintFor* ##1 in {\xintSeq {1}{\ListeQuestionColonneUnlen}}\do{%
+ \xintifboolexpr{\listlen\ListeQuestionColonneUn[##1]==2}{%
\uppercase{&}}{%
- \Block[l]{\fpeval{\ListeQuestionColonneUn[##4,1]}-1}{\ifboolKV[ClesFicheMemo]{Solution}{\ListeQuestionColonneUn[##4,3]}{}}\uppercase{&}\xdef\CountcolUn{\fpeval{\CountcolUn+1}}\Block[l]{\fpeval{\ListeQuestionColonneUn[##4,1]}-1}{\ListeQuestionColonneUn[##4,2]}%
+ \Block[l]{\fpeval{\ListeQuestionColonneUn[##1,1]}-1}{\ifboolKV[ClesFicheMemo]{Solution}{\ListeQuestionColonneUn[##1,3]}{}}%
+ \uppercase{&}\xdef\CountcolUn{\fpeval{\CountcolUn+1}}\Block[l]{\fpeval{\ListeQuestionColonneUn[##1,1]}-1}{\ListeQuestionColonneUn[##1,2]}%
}%
&%
- \xintifboolexpr{\listlen\ListeQuestionColonneDeux[##4]==2}{%
+ \xintifboolexpr{\listlen\ListeQuestionColonneDeux[##1]==2}{%
\uppercase{&}%
}{%
- \xdef\CountcolDeux{\fpeval{\CountcolDeux+1}}\Block[l]{\fpeval{\ListeQuestionColonneDeux[##4,1]}-1}{\ListeQuestionColonneDeux[##4,2]}\uppercase{&}\Block[l]{\fpeval{\ListeQuestionColonneDeux[##4,1]}-1}{\ifboolKV[ClesFicheMemo]{Solution}{\ListeQuestionColonneDeux[##4,3]}{}}%
+ \xdef\CountcolDeux{\fpeval{\CountcolDeux+1}}\Block[l]{\fpeval{\ListeQuestionColonneDeux[##1,1]}-1}{\ListeQuestionColonneDeux[##1,2]}\uppercase{&}\Block[l]{\fpeval{\ListeQuestionColonneDeux[##1,1]}-1}{\ifboolKV[ClesFicheMemo]{Solution}{\ListeQuestionColonneDeux[##1,3]}{}}%
}%
\\%
}%
\CodeAfter%
\tikz\node[xshift=0.5em] at (2-|1) {\scriptsize\faCut};%
\xdef\PfCCountCutUn{2}%
- \xintFor* ##4 in {\xintSeq {1}{\ListeQuestionColonneUnlen}}\do{%
- \xintifboolexpr{\listlen\ListeQuestionColonneUn[##4]==2}{%
+ \xintFor* ##1 in {\xintSeq {1}{\ListeQuestionColonneUnlen}}\do{%
+ \xintifboolexpr{\listlen\ListeQuestionColonneUn[##1]==2}{%
}{%
- \xdef\PfCCountCutUn{\fpeval{\PfCCountCutUn+\ListeQuestionColonneUn[##4,1]}}%
+ \xdef\PfCCountCutUn{\fpeval{\PfCCountCutUn+\ListeQuestionColonneUn[##1,1]}}%
\tikz\node[xshift=0.5em] at (\fpeval{\PfCCountCutUn}-|1) {\scriptsize\faCut};%
}%
}%
\tikz\node[xshift=-0.5em] at (2-|last) {\scriptsize\rotatebox{180}{\faCut}};%
\xdef\PfCCountCutDeux{2}%
- \xintFor* ##4 in {\xintSeq {1}{\ListeQuestionColonneDeuxlen}}\do{%
- \xintifboolexpr{\listlen\ListeQuestionColonneDeux[##4]==2}{%
+ \xintFor* ##1 in {\xintSeq {1}{\ListeQuestionColonneDeuxlen}}\do{%
+ \xintifboolexpr{\listlen\ListeQuestionColonneDeux[##1]==2}{%
}{%
- \xdef\PfCCountCutDeux{\fpeval{\PfCCountCutDeux+\ListeQuestionColonneDeux[##4,1]}}%
+ \xdef\PfCCountCutDeux{\fpeval{\PfCCountCutDeux+\ListeQuestionColonneDeux[##1,1]}}%
\tikz\node[xshift=-0.5em] at (\fpeval{\PfCCountCutDeux}-|last) {\scriptsize\rotatebox{180}{\faCut}};%
}%
}%
@@ -1163,6 +1876,7 @@
\tikz\node at (1.5-|3.5) {\bfseries\useKV[ClesFicheMemo]{TexteQuestions} \num{\fpeval{\CountcolUn+1}} à \num{\fpeval{\CountcolUn+\CountcolDeux}}};%
\end{NiceTabular}%
\renewcommand{\arraystretch}{1}%
+ \setsepchar{,}%
}%
%%%
@@ -1170,9 +1884,9 @@
%%%
%% D'après https://tex.stackexchange.com/questions/277246/drawing-a-circle-around-the-numbers-in-xlop-package
-\newcommand{\PfCchiffre}[2]{\tikz[remember picture] \node[inner sep=0pt](#1){#2};}
+\newcommand\PfCchiffre[2]{\tikz[remember picture] \node[inner sep=0pt](#1){#2};}
-\newcommand{\PfCentoure}[2]{\tikz[remember picture,overlay] \node[preaction={draw={\useKV[ClesOperations]{CouleurCadre}},ultra thick,opacity=1,
+\newcommand\PfCentoure[2]{\tikz[remember picture,overlay] \node[preaction={draw={\useKV[ClesOperations]{CouleurCadre}},ultra thick,opacity=1,
transform canvas={xshift=0em,yshift=0em}},rectangle,rounded corners,ultra thick,inner sep=.55em,fit=(#1.center)(#2.center)]{} ;}
\newcounter{divxlop}%
@@ -2097,6 +2811,7 @@ transform canvas={xshift=0em,yshift=0em}},rectangle,rounded corners,ultra thick,
\dtlexpandnewvalue%
\DTLgnewdb{mtnumedb}%
+\DTLgnewdb{mtRGTdb}% Pb de doublon avec mtdb de Mediane
\newcommand\Rangement[2][]{%
\useKVdefault[ClesRgt]%
@@ -2111,48 +2826,48 @@ transform canvas={xshift=0em,yshift=0em}},rectangle,rounded corners,ultra thick,
}%
% On cr\'ee la liste des rangements.
\DTLcleardb{mtnumedb}%
- % on les trie pour les ranger par ordre croissant
+% % on les trie pour les ranger par ordre croissant
\foreachitem\x\in\ListeRgt{%
\DTLnewrow{mtnumedb}%
\xdef\toto{\fpeval{\ListeRgt[\xcnt,1]*\the\ppcm/\ListeRgt[\xcnt,2]}}%
\DTLnewdbentry{mtnumedb}{numeric}{\toto}%
}%
- % On trie
+% % On trie
\ifboolKV[ClesRgt]{Decroissant}{%
- % On trie la liste
+% % On trie la liste
\dtlsort{numeric=descending}{mtnumedb}{\dtlicompare}%
\ifboolKV[ClesRgt]{Details}{\ensuremath{\DTLforeach{mtnumedb}{\numeroDonnee=numeric}{\frac{\num{\numeroDonnee}}{\num{\the\ppcm}}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{>}{\geqslant}}}}}{%
\ensuremath{\DTLforeach{mtnumedb}{\numeroDonnee=numeric}{\Simplification{\numeroDonnee}{\ppcm}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{>}{\geqslant}}}}%
}
}{%
- % On trie la liste
+% % On trie la liste
\dtlsort{numeric}{mtnumedb}{\dtlicompare}%
\ifboolKV[ClesRgt]{Details}{%
\ensuremath{\DTLforeach{mtnumedb}{\numeroDonnee=numeric}{\frac{\num{\numeroDonnee}}{\num{\the\ppcm}}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{<}{\leqslant}}}}%
}{%
\ensuremath{\DTLforeach{mtnumedb}{\numeroDonnee=numeric}{\Simplification{\numeroDonnee}{\ppcm}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{<}{\leqslant}}}}%
- }
+ }%
}%
}{%
\setsepchar{,}\ignoreemptyitems%
\readlist*\ListeRgt{#2}%
% on cr\'ee la base de donn\'ees des valeurs
- \DTLcleardb{mtdb}%
- % on les trie pour les ranger par ordre croissant
+ \DTLcleardb{mtRGTdb}%
+% % on les trie pour les ranger par ordre croissant
\foreachitem\x\in\ListeRgt{%
- \DTLnewrow{mtdb}%
+ \DTLnewrow{mtRGTdb}%
\itemtomacro\ListeRgt[\xcnt]\y%
- \DTLnewdbentry{mtdb}{numeric}{\y}%
+ \DTLnewdbentry{mtRGTdb}{numeric}{\y}%
}%
- %
+% %
\ifboolKV[ClesRgt]{Decroissant}{%
% On trie la liste
- \dtlsort{numeric=descending}{mtdb}{\dtlicompare}%
- \ensuremath{\DTLforeach{mtdb}{\numeroDonnee=numeric}{\num{\numeroDonnee}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{>}{\geqslant}}}}%
+ \dtlsort{numeric=descending}{mtRGTdb}{\dtlicompare}%
+ \ensuremath{\DTLforeach{mtRGTdb}{\numeroDonnee=numeric}{\num{\numeroDonnee}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{>}{\geqslant}}}}%
}{%
- % On trie la liste
- \dtlsort{numeric}{mtdb}{\dtlicompare}%
- \ensuremath{\DTLforeach{mtdb}{\numeroDonnee=numeric}{\num{\numeroDonnee}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{<}{\leqslant}}}}%
+% % On trie la liste
+ \dtlsort{numeric}{mtRGTdb}{\dtlicompare}%
+ \ensuremath{\DTLforeach{mtRGTdb}{\numeroDonnee=numeric}{\num{\numeroDonnee}\DTLiflastrow{}{\ifboolKV[ClesRgt]{Strict}{<}{\leqslant}}}}%
}%
}%
}%
@@ -3771,7 +4486,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
\foreach \i in {1,...,3}{%
\coordinate[xshift=\i*0.25*\paperwidth] (A\i) at (current page.north west);%
\coordinate[xshift=\i*0.25*\paperwidth] (B\i) at (current page.south west);%
- }
+ }%
\foreach \i in{1,...,4}{%
\coordinate[yshift=-\i*0.25*\paperheight] (C\i) at (current page.north west);%
\coordinate[yshift=-\i*0.25*\paperheight] (F\i) at (current page.north east);%
@@ -3894,10 +4609,10 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
\node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(V3)!0.5!(V4)$) {\ListeAutoEn[2,1]};%
\node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(V5)!0.5!(V6)$) {\ListeAutoEn[3,1]};%
\node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(V7)!0.5!(V8)$) {\ListeAutoEn[4,1]};%
- \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R1)!0.5!(R2)$) {\ListeAutoQ[1,2]};%
- \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R3)!0.5!(R4)$) {\ListeAutoQ[2,2]};%
- \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R5)!0.5!(R6)$) {\ListeAutoQ[3,2]};%
- \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R7)!0.5!(R8)$) {\ListeAutoQ[4,2]};%
+ \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R1)!0.5!(R2)$) {\ListeAutoQ[1,2]};%%
+ \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R3)!0.5!(R4)$) {\ListeAutoQ[2,2]};%%
+ \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R5)!0.5!(R6)$) {\ListeAutoQ[3,2]};%%
+ \node[align=justify,anchor=center,text width=0.9*0.25\textwidth] at ($(R7)!0.5!(R8)$) {\ListeAutoQ[4,2]};%%
}{%
\foreach \i in {1,...,8}{%
\node[text width=0.9*0.25\paperwidth] at (V\i) {\ListeAutoQ[\i,2]};%
@@ -5982,7 +6697,16 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
cc=fullcircle scaled 1u;
% on marque les angles
picture MAngle;
- MAngle=image(
+ MAngle=image(%
+ if #6=0:%Pour l'isocèle
+ path cd; pair M[];
+ cd=B--(A+B+C)/3;
+ M1=cd intersectionpoint (cc shifted B);
+ trace 9/10[B,M1]--11/10[B,M1];
+ cd:=C--(A+B+C)/3;
+ M1:=cd intersectionpoint (cc shifted C);
+ trace 9/10[C,M1]--11/10[C,M1];
+ fi;
draw (cc shifted A);
draw (cc shifted B);
draw (cc shifted C);
@@ -6490,9 +7214,11 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
\xintifboolexpr{#3<#4 || #3==#4}{
\xdef\PetitCote{#3}%
\xdef\MoyenCote{#4}%
+ \xdef\GrandCote{}%
}{%
\xdef\GrandCote{#3}%
\xdef\MoyenCote{#4}%
+ \xdef\PetitCote{}% Pour la personnalisation
}
% On retient les noms des sommets
\StrMid{#2}{1}{1}[\NomA]%
@@ -6613,13 +7339,13 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
% Distributivit\'e
%%%
% https://tex.stackexchange.com/questions/168972/draw-arrows-to-show-multiplication-pattern-distributive-property/169278?noredirect=1
-\newcommand{\Tikzmark}[1]{%
+\newcommand\Tikzmark[1]{%
\tikz[remember picture,baseline,inner sep=0pt]{%
\node[name=Distri-\theNbDistri,anchor=base] {${#1}$};}%
\stepcounter{NbDistri}%
}%
-\newcommand{\DrawArrow}{%
+\newcommand\DrawArrow{%
\begin{tikzpicture}[overlay,remember picture]
\draw[-stealth,out=50,in=140,DCFlechesh,transform canvas={yshift=2pt}] (Distri-0.north) to (Distri-2.north);
\draw[-stealth,out=50,in=140,DCFlechesh!50,transform canvas={yshift=2pt}] (Distri-0.north) to (Distri-3.north);
@@ -7016,7 +7742,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
\xdef\SommeB{0}%
\xdef\SommeC{0}%
-\newcommand{\Distri}[5][]{%
+\newcommand\Distri[5][]{%
\useKVdefault[ClesDistributivite]%obligatoire car la macro n'est pas dans un groupe.
\setKV[ClesDistributivite]{#1}%On lit les arguments optionnels
\ifboolKV[ClesDistributivite]{RAZ}{\xdef\SommeA{0}\xdef\SommeB{0}\xdef\SommeC{0}%
@@ -7292,7 +8018,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
}%
}%
-\newcommand{\DistriEchange}[5][]{%
+\newcommand\DistriEchange[5][]{%
\ensuremath{%
\useKVdefault[ClesDistributivite]%obligatoire car la macro n'est pas dans un groupe.
\setKV[ClesDistributivite]{#1}%On lit les arguments optionnels
@@ -8529,7 +9255,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
}
-\newcommand{\SSimpli}[2]{%
+\newcommand\SSimpli[2]{%
% D\'ecomposition d'une simplification de #1/#2
\newcount\numerateur\newcount\denominateur\newcount\valabsnum\newcount\valabsdeno%
\numerateur=\number#1
@@ -9092,7 +9818,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
\newcommand\EcritureQuotients{}%
%%%
-\newcommand{\TTThales}[6][]{%
+\newcommand\TTThales[6][]{%
\useKVdefault[ClesThales]%
\setKV[ClesThales]{#1}%
\ifboolKV[ClesThales]{Perso}{\RedactionThales}{%
@@ -9121,7 +9847,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
}%
}%
-\newcommand{\TThalesCalculsD}[8][]{%
+\newcommand\TThalesCalculsD[8][]{%
\setKV[ClesThales]{#1}%
\newcount\zzz\newcount\yyy\newcount\xxx%Pour se rappeller des calculs \`a faire et combien en faire%
\def\Nomx{}%
@@ -9359,7 +10085,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
}{}
}
-\newcommand{\TThalesCalculsE}[8][]{%
+\newcommand\TThalesCalculsE[8][]{%
\setKV[ClesThales]{#1}%
\newcount\zzz\newcount\yyy\newcount\xxx%Pour se rappeller des calculs \`a faire et combien en faire%
\newcount\valx\newcount\Valx%
@@ -9682,7 +10408,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
}{}%
}
-\newcommand{\TThales}[8][]{%
+\newcommand\TThales[8][]{%
\setKV[ClesThales]{#1}%
\StrMid{#2}{1}{1}[\NomA]\StrMid{#2}{2}{2}[\NomB]\StrMid{#2}{3}{3}[\NomC]\StrMid{#2}{4}{4}[\NomM]\StrMid{#2}{5}{5}[\NomN]%
\ifboolKV[ClesThales]{FigureSeule}{%
@@ -9733,7 +10459,7 @@ couleur indiquée, le nombre de cases donné par le résultat du calcul.
}
}
-\newcommand{\ReciThalesCalculs}[8][]{%
+\newcommand\ReciThalesCalculs[8][]{%
\StrMid{#2}{1}{1}[\NomA]%
\StrMid{#2}{2}{2}[\NomB]%
\StrMid{#2}{3}{3}[\NomC]%
@@ -10587,7 +11313,7 @@ Rayon=3cm,AffichageAngle=false,AffichageDonnee=false,ListeCouleurs={white},Hachu
%Pour les représentations
Representation=false,%
%Pour les barres horizontales
-Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
+Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false,EcartBarre=0%Grille est dispo
}
%compl\'ements
\defKV[ClesStat]{AngleRotationAbscisse=\setKV[ClesStat]{AbscisseRotation}}%
@@ -10705,8 +11431,8 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
\xdef\PfCfooStat{\PfCfooStat \ListeComplete[##1,2],}%
}%
\xdef\DivMax{\fpeval{max(\PfCfooStat)}}%
- \xdef\DivMax{\fpeval{round(ln(\DivMax)/ln(10))}}%
- \xdef\DivMax{\fpeval{10**\DivMax}}%
+ \xdef\ExposantDivMax{\fpeval{round(ln(\DivMax)/ln(10))}}%
+ \xdef\DivMax{\fpeval{10**\ExposantDivMax}}%
\xdef\PfCfooStat{}%
\xintFor* ##1 in {\xintSeq {1}{\ListeCompletelen}}\do{%
\xdef\PfCfooStat{\PfCfooStat \ListeComplete[##1,1]/\ListeComplete[##1,2]/\fpeval{\ListeComplete[##1,2]/\DivMax},}%
@@ -10799,17 +11525,25 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
% #2 Liste des valeurs associées
% #3 Liste des valeurs à afficher (si pb calcul MP)
% #4 Liste des couleurs
- \ifluatex
+ \ifluatex%
\mplibforcehmode%
\begin{mplibcode}%
Longueur:=\useKV[ClesStat]{Longueur};
Hauteur:=\useKV[ClesStat]{Hauteur};
+ Ecart:=\useKV[ClesStat]{EcartBarre};
+ ExposantDivMax:=\ExposantDivMax;
ecarthachures=\useKV[ClesStat]{EcartHachures};
epaisseurhachures=\useKV[ClesStat]{EpaisseurHachures};
boolean Hachures;
Hachures=\useKV[ClesStat]{Hachures};
boolean Bicolore;
Bicolore=\useKV[ClesStat]{Bicolore};
+ boolean Grille;
+ Grille=\useKV[ClesStat]{Grille};
+ boolean AffichageDonnee;
+ AffichageDonnee=\useKV[ClesStat]{AffichageDonnee};
+ boolean LegendeVide;
+ LegendeVide=\useKV[ClesStat]{LegendeVide};
vardef CalculNombreDonneesEtDonneeMax(text t)=
nbdon:=0;%nombre de données
DonneeMax:=0;%donnée DonneeMaximale
@@ -10836,10 +11570,40 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
endfor;
enddef;
vardef TraceDiag=
+ if Grille:
+ pair Zz[];%Pour déterminer "le dernier point"
+ Zz0=(0,-(nbdon-1)*(Hauteur+Ecart)-Ecart);
+ Zz2=(0,(Hauteur+Ecart));
+ Zz1=((1/DonneeMax)*Longueur,-(nbdon-1)*(Hauteur+Ecart)-Ecart);
+ Zz3=if ExposantDivMax=0 : (DonneeMax+1)[Zz0,Zz1] else: ((floor(DonneeMax*10+2))/10)[Zz0,Zz1];fi;
+ if ExposantDivMax=0:
+ for k=1 upto DonneeMax+1:
+ trace (Zz0--Zz2) shifted (k*(Zz1-Zz0)) dashed evenly withcolor 0.5white;
+ endfor;
+ else:
+ for k=1 upto (floor(DonneeMax*10+2)):
+ trace (Zz0--Zz2) shifted ((k/10)*(Zz1-Zz0)) dashed evenly withcolor 0.5white;
+ endfor;
+ fi;
+ if ExposantDivMax=0:
+ for k=1 upto (DonneeMax+1):
+ label.bot(TEX("\num{"&decimal(k)&"}"),Zz0+k*(Zz1-Zz0));
+ endfor;
+ else:
+ if ExposantDivMax<5:
+ for k=1 upto (floor(DonneeMax*10+2)):
+ label.bot(TEX("\num{\fpeval{"&decimal(k)&"*(10**"&decimal(ExposantDivMax-1)&")}}"),Zz0+(k/10)*(Zz1-Zz0));
+ endfor;
+ else:
+ dotlabel.bot(TEX("\num{\fpeval{10**"&decimal(ExposantDivMax)&"}}"),Zz1);
+ fi;
+ fi;
+ fi;
for k=0 upto nbdon-1:
path RectangleDonnee;
- RectangleDonnee=(unitsquare xscaled ((Donnees[k+1]/DonneeMax)*Longueur) yscaled Hauteur) shifted(0,-k*Hauteur);
+ RectangleDonnee=(unitsquare xscaled ((Donnees[k+1]/DonneeMax)*Longueur) yscaled Hauteur) shifted(0,-k*(Hauteur+Ecart));
if Hachures:
+ fill RectangleDonnee withcolor white;
trace Hachurage(RectangleDonnee,60 if
(k mod 2)=0: +90 fi,ecarthachures,if (k mod 2)=0 : 0 else: 1 fi)
withpen pencircle scaled epaisseurhachures;
@@ -10848,18 +11612,22 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
fi;
trace RectangleDonnee;
endfor;
+ if Grille:
+ drawarrow (0,-(nbdon-1)*(Hauteur+Ecart)-Ecart)--(0,(Hauteur+Ecart)) withpen pencircle scaled 1.5;
+ drawarrow (0,-(nbdon-1)*(Hauteur+Ecart)-Ecart)--(Zz3+u*(0.25,0)) withpen pencircle scaled 1.5;
+ fi;
enddef;
vardef AffichageNom(text t)=
k:=0;
for p_=t:
- label.lft(TEX(p_),0.5[(0,0),(0,Hauteur)] shifted (0,-k*Hauteur));
+ label.lft(TEX(p_),0.5[(0,0),(0,Hauteur)] shifted (0,-k*(Hauteur+Ecart)));
k:=k+1;
endfor;
enddef;
vardef AffichageDonnees(text t)=
k:=0;
for p_=t:
- label.rt(TEX("\num{"&p_&"}"),0.5[(0,0),(0,Hauteur)] shifted (((Donnees[k+1]/DonneeMax)*Longueur),-k*Hauteur));
+ label.rt(TEX("\num{"&p_&"}"),0.5[(0,0),(0,Hauteur)] shifted (((Donnees[k+1]/DonneeMax)*Longueur),-k*(Hauteur+Ecart)));
k:=k+1;
endfor;
enddef;
@@ -10867,21 +11635,33 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
ListeDonnees(#2);
RecuperationCouleurs(#4);
TraceDiag;
+ if LegendeVide=false:
AffichageNom(#1);
+ fi;
+ if AffichageDonnee:
AffichageDonnees(#3);
+ fi;
\end{mplibcode}
- \else
+ \else%
\begin{mpost}[mpsettings={%
- Longueur:=\useKV[ClesStat]{Longueur};
- Hauteur:=\useKV[ClesStat]{Hauteur};
- ecarthachures=\useKV[ClesStat]{EcartHachures};
- epaisseurhachures=\useKV[ClesStat]{EpaisseurHachures};
- boolean Hachures;
- Hachures=\useKV[ClesStat]{Hachures};
- boolean Bicolore;
- Bicolore=\useKV[ClesStat]{Bicolore};
- }]
- vardef CalculNombreDonneesEtDonneeMax(text t)=
+ Longueur:=\useKV[ClesStat]{Longueur};
+ Hauteur:=\useKV[ClesStat]{Hauteur};
+ Ecart:=\useKV[ClesStat]{EcartBarre};
+ ExposantDivMax:=\ExposantDivMax;
+ ecarthachures=\useKV[ClesStat]{EcartHachures};
+ epaisseurhachures=\useKV[ClesStat]{EpaisseurHachures};
+ boolean Hachures;
+ Hachures=\useKV[ClesStat]{Hachures};
+ boolean Bicolore;
+ Bicolore=\useKV[ClesStat]{Bicolore};
+ boolean Grille;
+ Grille=\useKV[ClesStat]{Grille};
+ boolean AffichageDonnee;
+ AffichageDonnee=\useKV[ClesStat]{AffichageDonnee};
+ boolean LegendeVide;
+ LegendeVide=\useKV[ClesStat]{LegendeVide};
+ }]
+ vardef CalculNombreDonneesEtDonneeMax(text t)=
nbdon:=0;%nombre de données
DonneeMax:=0;%donnée DonneeMaximale
for p_=t:
@@ -10907,10 +11687,40 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
endfor;
enddef;
vardef TraceDiag=
+ if Grille:
+ pair Zz[];%Pour déterminer "le dernier point"
+ Zz0=(0,-(nbdon-1)*(Hauteur+Ecart)-Ecart);
+ Zz2=(0,(Hauteur+Ecart));
+ Zz1=((1/DonneeMax)*Longueur,-(nbdon-1)*(Hauteur+Ecart)-Ecart);
+ Zz3=if ExposantDivMax=0 : (DonneeMax+1)[Zz0,Zz1] else: ((floor(DonneeMax*10+2))/10)[Zz0,Zz1];fi;
+ if ExposantDivMax=0:
+ for k=1 upto DonneeMax+1:
+ trace (Zz0--Zz2) shifted (k*(Zz1-Zz0)) dashed evenly withcolor 0.5white;
+ endfor;
+ else:
+ for k=1 upto (floor(DonneeMax*10+2)):
+ trace (Zz0--Zz2) shifted ((k/10)*(Zz1-Zz0)) dashed evenly withcolor 0.5white;
+ endfor;
+ fi;
+ if ExposantDivMax=0:
+ for k=1 upto (DonneeMax+1):
+ label.bot(TEX("\num{"&decimal(k)&"}"),Zz0+k*(Zz1-Zz0));
+ endfor;
+ else:
+ if ExposantDivMax<5:
+ for k=1 upto (floor(DonneeMax*10+2)):
+ label.bot(TEX("\num{\noexpand\fpeval{"&decimal(k)&"*(10**"&decimal(ExposantDivMax-1)&")}}"),Zz0+(k/10)*(Zz1-Zz0));
+ endfor;
+ else:
+ dotlabel.bot(TEX("\num{\noexpand\fpeval{10**"&decimal(ExposantDivMax)&"}}"),Zz1);
+ fi;
+ fi;
+ fi;
for k=0 upto nbdon-1:
path RectangleDonnee;
- RectangleDonnee=(unitsquare xscaled ((Donnees[k+1]/DonneeMax)*Longueur) yscaled Hauteur) shifted(0,-k*Hauteur);
+ RectangleDonnee=(unitsquare xscaled ((Donnees[k+1]/DonneeMax)*Longueur) yscaled Hauteur) shifted(0,-k*(Hauteur+Ecart));
if Hachures:
+ fill RectangleDonnee withcolor white;
trace Hachurage(RectangleDonnee,60 if
(k mod 2)=0: +90 fi,ecarthachures,if (k mod 2)=0 : 0 else: 1 fi)
withpen pencircle scaled epaisseurhachures;
@@ -10919,18 +11729,22 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
fi;
trace RectangleDonnee;
endfor;
+ if Grille:
+ drawarrow (0,-(nbdon-1)*(Hauteur+Ecart)-Ecart)--(0,(Hauteur+Ecart)) withpen pencircle scaled 1.5;
+ drawarrow (0,-(nbdon-1)*(Hauteur+Ecart)-Ecart)--(Zz3+u*(0.25,0)) withpen pencircle scaled 1.5;
+ fi;
enddef;
vardef AffichageNom(text t)=
k:=0;
for p_=t:
- label.lft(LATEX(p_),0.5[(0,0),(0,Hauteur)] shifted (0,-k*Hauteur));
+ label.lft(TEX(p_),0.5[(0,0),(0,Hauteur)] shifted (0,-k*(Hauteur+Ecart)));
k:=k+1;
endfor;
enddef;
vardef AffichageDonnees(text t)=
k:=0;
for p_=t:
- label.rt(LATEX("\num{"&p_&"}"),0.5[(0,0),(0,Hauteur)] shifted (((Donnees[k+1]/DonneeMax)*Longueur),-k*Hauteur));
+ label.rt(TEX("\num{"&p_&"}"),0.5[(0,0),(0,Hauteur)] shifted (((Donnees[k+1]/DonneeMax)*Longueur),-k*(Hauteur+Ecart)));
k:=k+1;
endfor;
enddef;
@@ -10938,10 +11752,14 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
ListeDonnees(#2);
RecuperationCouleurs(#4);
TraceDiag;
+ if LegendeVide=false:
AffichageNom(#1);
+ fi;
+ if AffichageDonnee:
AffichageDonnees(#3);
+ fi;
\end{mpost}
- \fi
+ \fi%
}%
% la construction du graphique en bâtons pour quantitatif
@@ -12446,7 +13264,7 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
%Une simplification de a/b est possible ou non ?
\newboolean{Simplification}
-\newcommand{\SSimpliTest}[2]{%
+\newcommand\SSimpliTest[2]{%
% Test d'une simplification possible ou pas de #1/#2
\newcount\numerateur\newcount\denominateur\newcount\valabsnum\newcount\valabsdeno%
\numerateur=\number#1
@@ -13258,13 +14076,13 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
\end{tabular}%
}%
-\newcommand{\TikzRH}{%
+\newcommand\TikzRH{%
\tikz[remember picture,overlay]{%
\coordinate[name=ProporH-\theNbPropor,yshift=\getstrut\ht*\arraystretch];}%
\stepcounter{NbPropor}%
}%
- \newcommand{\TikzRB}{%
+ \newcommand\TikzRB{%
\tikz[remember picture, overlay]{%
\coordinate[name=ProporB-\theNbPropor,yshift=-\getstrut\dp*\arraystretch];}%
\stepcounter{NbPropor}%
@@ -13490,7 +14308,7 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
\def\MPFigureDroite#1#2{%
\ifluatex
- \mplibcodeinherit{enable}
+ %\mplibcodeinherit{enable}
\mplibforcehmode
\begin{mplibcode}
pair A,B,C,D,E,F,G,H,I,J,K;
@@ -13574,7 +14392,7 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
reste:=reste rotatedabout(u*(3,3),-90+uniformdeviate(180));
draw reste;
\end{mplibcode}
- \mplibcodeinherit{disable}
+ %\mplibcodeinherit{disable}
\else
\begin{mpost}
pair A,B,C,D,E,F,G,H,I,J,K;
@@ -17687,7 +18505,7 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
if p_<>"":
drawarrow (unitp*(valeur[n],-1))--(unitp*(valeur[n],-0.3));
label.bot(btex \hbox to2em{\dotfill} etex,(unitp*(valeur[n],-1)));
- pointe(unitp*(valeur[n]-ValeurOrigine,0));
+ pointe(unitp*(valeur[n],0));
fi;
endfor;
elseif AffichageCoord=2:
@@ -17700,7 +18518,7 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
else:
label.bot(TEX("\footnotesize\num{\fpeval{"&decimal(ValeurUnitex)&"*"&decimal(valeur[n])&"/"&decimal(pasx)&"}}"),unitp*(valeur[n],0));
fi;
- pointe(unitp*(valeur[n]-ValeurOrigine,0));
+ pointe(unitp*(valeur[n],0));
fi;
endfor;
elseif AffichageCoord=1:
@@ -18218,58 +19036,59 @@ Barre=false,Longueur=10cm,Hauteur=5mm,Bicolore=false%
%D'apres https://tex.stackexchange.com/questions/38905/time-of-the-day-or-time-period-using-the-package-siunitx
\ExplSyntaxOn
\NewDocumentCommand \Temps { o > { \SplitArgument { 5 } { ; } } m }
-{
- \group_begin:
- \IfNoValueF {#1}
+{%
+ \group_begin:%
+ \IfNoValueF{#1}
{ \keys_set:nn { siunitx } {#1} }
\siunitx_hms_output:nnn #2
\group_end:
}
\cs_new_protected:Npn \siunitx_hms_output:nnn #1#2#3#4#5#6
-{
- \IfNoValueF {#1}
- {
- \tl_if_blank:nF {#1}
- {
- \SI {#1} { \annee\xintifboolexpr{#1>1}{s}{} }
- \IfNoValueF {#2} { ~ }
- }
- }
- \IfNoValueF {#2}
- {
- \tl_if_blank:nF {#2}
- {
- \SI {#2} { \mois }
- \IfNoValueF {#3} { ~ }
- }
- }
- \IfNoValueF {#3}
- {
- \tl_if_blank:nF {#3}
- {
- \SI {#3} { \jour }
- \IfNoValueF {#4} { ~ }
- }
- }
- \IfNoValueF {#4}
- {
- \tl_if_blank:nF {#4}
- {
- \SI {#4} { \hour }
- \IfNoValueF {#5} { ~ }
- }
- }
- \IfNoValueF {#5}
- {
- \tl_if_blank:nF {#5}
- {
- \SI {#5} { \minute }
- \IfNoValueF {#6} { ~ }
- }
- }
- \IfNoValueF {#6}
- { \tl_if_blank:nF {#6} { \SI {#6} { \second } } }
-}
+{%
+ \IfNoValueF {#1}%
+ {%
+ \tl_if_blank:nF {#1}%
+ {%
+ \SI{#1}{\annee\xintifboolexpr{#1>1}{s}{}}%
+ \IfNoValueF {#2}{~}%
+ }%
+ }%
+ \IfNoValueF {#2}%
+ {%
+ \tl_if_blank:nF {#2}%
+ {%
+ \SI{#2}{\mois}%
+ \IfNoValueF{#3}{~}%
+ }%
+ }%
+ \IfNoValueF {#3}%
+ {%
+ \tl_if_blank:nF {#3}%
+ {%
+ \SI{#3}{\jour}%
+ \IfNoValueF{#4}{~}%
+ }%
+ }%
+ \IfNoValueF {#4}%
+ {%
+ \tl_if_blank:nF {#4}%
+ {%
+ \SI{#4}{\hour}%
+ \IfNoValueF{#5}{~}%
+ }%
+ }%
+ \IfNoValueF {#5}%
+ {%
+ \tl_if_blank:nF {#5}%
+ {%
+ \SI[minimum-integer-digits=2]{#5}{\minute}%
+ \IfNoValueF{#6}{~}%
+ }%
+ }%
+ \IfNoValueF {#6}%
+ {%
+ \tl_if_blank:nF {#6} {\SI{#6}{\second}}}%
+}%
\ExplSyntaxOff
\newcommand\Temp[2][]{%
diff --git a/macros/latex/contrib/profcollege/metapost/PfCGeometrie.mp b/macros/latex/contrib/profcollege/metapost/PfCGeometrie.mp
index 3386a78680..02a3f66ce2 100644
--- a/macros/latex/contrib/profcollege/metapost/PfCGeometrie.mp
+++ b/macros/latex/contrib/profcollege/metapost/PfCGeometrie.mp
@@ -1276,4 +1276,240 @@ vardef Tetraedrer(text t)=
tetrar
enddef;
+%Outils
+numeric echelleequerre;
+echelleequerre=2;
+vardef equerre(expr dte,drte,perpe,sens)=
+ save picequerre;
+ picture picequerre;
+ pair ww,t[];
+ path intermede;
+ pair perpen,ptt,pttt;
+ perpen:=projection(perpe,dte,drte);
+ %if sens=1 :
+ ptt:=longueurequerre*(drte-dte) rotated 90 shifted perpen;
+ %else :
+% ptt:=longueurequerre*(drte-dte) rotated (-90) shifted perpen;
+ %fi;
+ ww=unitvector(drte-dte);
+ intermede=ptt--(10[ptt,(perpen rotatedabout(ptt,if sens=1: 30 else:-30 fi))]);
+ pttt=intermede intersectionpoint (10[dte,drte]--10[drte,dte]);
+ picequerre=image(
+ draw perpen--ptt--pttt--cycle;
+ draw codeperp(ptt,perpen,pttt,5);
+ );
+ picequerre
+enddef;
+
+ vardef regle(expr depart,arrivee,rr)=
+ save picregle;
+ picture picregle,grad[],gradu[],final;
+ pair t[];
+ path reduit;
+ t1000=depart shifted (5*unitvector(depart-arrivee));
+ t1003=arrivee shifted (20*unitvector(arrivee-depart));
+ t1004=(unitvector(arrivee-depart) rotated (-90)) shifted t1000;
+ t1001=t1000 shifted (50*(t1004-t1000));
+ t1002=t1001 shifted (t1003-t1000);
+ reduit=t1000--t1001--t1002..(t1002 shifted(5*unitvector(t1001-t1002)+1/4(t1003-t1002)))..(t1002 shifted(5*unitvector(t1002-t1001)+2/4(t1003-t1002)))..(t1002 shifted(5*unitvector(t1001-t1002)+3/4(t1003-t1002)))..t1003--cycle;
+ gradu1=image(
+ for k=0 upto 59:
+ for j=1 upto 4:
+ t[5*k+j]=depart shifted (1mm*(5*k+j)*unitvector(arrivee-depart));
+ t[400+5*k+j]=t[5*k+j] shifted (2*(t1004-t1000));
+ draw t[5*k+j]--t[400+5*k+j];
+ endfor;
+ endfor
+ );
+ gradu2=image(
+ for k=0 upto 29:
+ t[5*(2*k+1)]=depart shifted (1mm*5*(2*k+1)*unitvector(arrivee-depart));
+ t[400+5*(2*k+1)]=t[5*(2*k+1)] shifted (5*(t1004-t1000));
+ draw t[5*(2*k+1)]--t[400+5*(2*k+1)];
+ endfor
+ );
+ gradu3=image(
+ for k=0 upto 30:
+ t[10*k]=depart shifted(1mm*10*k*unitvector(arrivee-depart));
+ t[400+10*k]=t[10*k] shifted (10*(t1004-t1000));
+ draw t[10*k]--t[400+10*k];
+ endfor
+ );
+ for j=0 upto 30:
+ grad[j]=image(
+ label.bot(TEX(""&decimal(j)&""),t[400+10*j]);
+ %affixe[j](t[400+10*j])s;
+ currentpicture:=currentpicture rotatedabout(t[400+10*j],90+angle(t[400+10*j]-t[10*j]));
+ );
+ endfor
+ final=image(
+ for k=0 upto 30:
+ draw grad[k];
+ endfor
+ for k=1 upto 3:
+ draw gradu[k];
+ endfor
+ clip currentpicture to reduit;
+ draw reduit;
+ );
+ if rr=-1:
+ picregle=image(
+ draw final rotatedabout(1/2[depart,arrivee],180);
+ );
+ else:
+ picregle=image(
+ draw final;
+ );
+ fi
+ picregle
+enddef;
+
+vardef crayon(expr depart,arrive,ptplace,nbechelle)=
+ save piccray;
+ picture piccray,crayolat;
+ pair w[];
+ w0=(0,0);
+ w1=(1,2)*u/2;
+ w2=(-1,2)*u/2;
+ w3=(0,2)*u/2;
+ w4=(0,7)*u/2;
+ path ccc,ccd;
+ ccc=cercles(w0,abs(w3-w2));
+ ccd=ccc yscaled 0.25 shifted w3;
+ crayolat=image(
+ draw subpath((length ccd)/2,length ccd) of ccd;
+ draw ccd shifted (w4-w3);
+ draw w2--w0--w1;
+ draw w1--((1,7)*u/2);
+ draw w2--((-1,7)*u/2);
+ );
+ crayolat:=crayolat scaled nbechelle;
+ piccray=(crayolat rotated(angle(arrive-depart)-30)) shifted ptplace;
+ piccray
+enddef;
+
+boolean Simple;
+Simple=false;
+
+vardef rapporteur(expr centre,segment,rr)=
+ save raps;
+ picture raps;
+ raps=image(
+ Simple:=true;
+ trace rapporteurdouble(centre,segment,rr);
+ Simple:=false;
+ );
+ raps
+enddef;
+
+vardef rapporteurdouble(expr centre,segment,rr)=
+ save rap,cc,cd,v,w,t,ww,vv;
+ picture rap;
+ path cc,cd;
+ pair a[],b[],v,w,t,ww,vv,rap[],rapp[];
+ cc=cercle(centre,0.75*abs(centre-segment));
+ t=cc intersectionpoint (centre--segment);
+ w=t-2*unitvector(segment-centre);v=symetrie(w,t);
+ ww=t-5*unitvector(segment-centre);vv=symetrie(ww,t);
+ a0=(ww-centre) shifted centre;
+ b0=(vv-centre) shifted centre;
+ for i=0 upto 35 :
+ for j=1 upto 4 :
+ a[5*i+j]=(w-centre) rotated (rr*(5*i+j)) shifted centre;
+ b[5*i+j]=(v-centre) rotated (rr*(5*i+j)) shifted centre;
+ endfor;
+ a[5*(i+1)]=(ww-centre) rotated (rr*(5*(i+1))) shifted centre;
+ b[5*(i+1)]=(vv-centre) rotated (rr*(5*(i+1))) shifted centre;
+ endfor
+ picture nomb[],nombre[];
+ if rr=1:
+ for j=0 upto 18:
+ nombre[10*j]=image(
+ label.bot(TEX("\fontsize{4}{4}\selectfont"&decimal(10*j)&""),a[10*j]);
+ currentpicture:=currentpicture rotatedabout(a[10*j],angle(a[10*j]-centre)-90);
+ );
+ endfor
+ for j=0 upto 18:
+ nombre[10*j+1]=image(
+ % affixe.[180-10*j](b[10*j])n;
+ label.top(TEX("\fontsize{4}{4}\selectfont"&decimal(180-10*j)&""),b[10*j]);
+ currentpicture:=currentpicture rotatedabout(b[10*j],angle(b[10*j]-centre)-90);
+ );
+ endfor
+ else:
+ for j=0 upto 18:
+ nombre[10*j]=image(
+ label.bot(TEX("\fontsize{4}{4}\selectfont"&decimal(180-10*j)&""),a[10*j]);
+ currentpicture:=currentpicture rotatedabout(a[10*j],angle(a[10*j]-centre)-90);
+ );
+ endfor
+ for j=18 downto 0:
+ nombre[10*j+1]=image(
+ % affixe.[10*j](b[10*j])n;
+ label.top(TEX("\fontsize{4}{4}\selectfont"&decimal(10*j)&""),b[10*j]);
+ currentpicture:=currentpicture rotatedabout(b[10*j],angle(b[10*j]-centre)-90);
+ );
+ endfor
+ fi
+ rap=image(
+ for i=0 upto 18 :
+ draw nombre[10*i+1];
+ if Simple=false:
+ draw nombre[10*i];
+ fi;
+ endfor;
+ path cerc;
+ cerc=subpath((angle(segment-centre)*(length cc))/360,((length cc)/2)+(angle(segment-centre)*(length cc))/360) of cc;
+ if rr=-1:
+ draw cerc reflectedabout(segment,centre);
+ else:
+ draw cerc;
+ fi
+ draw a0--b0 withpen pencircle scaled 1.25bp;
+ for i=0 upto 35 :
+ for j=1 upto 4 :
+ draw a[5*i+j]--b[5*i+j];
+ endfor;
+ endfor;
+ for i=1 step 2 until 35:
+ draw a[5*i]--b[5*i];
+ endfor;
+ for i=1 upto 18:
+ draw a[10*i]--b[10i] withpen pencircle scaled 1.25;
+ endfor;
+ draw a0--a180;
+ path cent;
+ cent=cercle(centre,0.05*u);
+ fill cent withcolor if unknown fillrap: 0.9white else: fillrap fi;
+ );
+ rap
+enddef;
+
+vardef compas(expr centre,extre,n)=
+ save piccompas;
+ picture piccompas;
+ pair r,s,t,a,b,c,d,e,f;
+ if (abs(centre-extre)<10*u):
+ r=((extre-1/2[centre,extre]) rotated (n*90)) shifted (1/2[centre,extre]);
+ else:
+ r=0.25[1/2[centre,extre],((extre-1/2[centre,extre]) rotated (n*90)) shifted (1/2[centre,extre])];
+ fi
+ s=(1+50/abs(centre-extre))[1/2[centre,extre],r];
+ t=10*unitvector(extre-centre) rotated (n*90);
+ a=centre shifted t;
+ b=s shifted (5*unitvector(centre-extre)+10*unitvector(s-r));
+ c=b shifted (30*unitvector(s-r));
+ d=c reflectedabout(r,s);
+ e=b reflectedabout(r,s);
+ f=a reflectedabout(r,s);
+ path comp;
+ comp=a--b--c--d--e--f--s--a--cycle;
+ piccompas=image(
+ fill comp withcolor black;
+ draw centre--a withpen pencircle scaled 1.5bp;
+ draw f--extre withpen pencircle scaled 1.5bp withcolor 0.25[red,blue];
+ );
+ piccompas
+enddef;
+
endinput;
diff --git a/macros/latex/contrib/profcollege/metapost/PfCScratch.mp b/macros/latex/contrib/profcollege/metapost/PfCScratch.mp
index c3a41e3eb4..d8b2a0a851 100644
--- a/macros/latex/contrib/profcollege/metapost/PfCScratch.mp
+++ b/macros/latex/contrib/profcollege/metapost/PfCScratch.mp
@@ -122,7 +122,7 @@ vardef OvalVar(expr ar)=
save Ovar; picture Ovar;
save TAvar; path TAvar;
string TTv;
- TTv=ar&"\barre";
+ TTv="\barre\bfseries "&ar;%
TAvar=OvalBox(TTv);
Ovar=image(
fill TAvar if print=false : withcolor OrangeTrois else : withcolor white fi;
diff --git a/macros/luatex/generic/luakeys/README.md b/macros/luatex/generic/luakeys/README.md
index ca73100b64..2bff44088b 100644
--- a/macros/luatex/generic/luakeys/README.md
+++ b/macros/luatex/generic/luakeys/README.md
@@ -144,6 +144,18 @@ local opts = {
local result = luakeys.parse('one,two,three', opts)
```
+## Development
+
+`luakeys` is developed using the
+[Lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua)
+extension in Visual Studio Code. This extension understands the [EmmyLua
+annotations](https://github.com/sumneko/lua-language-server/wiki/EmmyLua-Annotations).
+The Lua source code documentation is generated with
+[LDoc](https://stevedonovan.github.io/ldoc/manual/doc.md.html).
+
+The Lua code is automatically formatted with the help of the
+[LuaFormatter](https://github.com/Koihik/LuaFormatter).
+
## Tasks
### Installing
@@ -154,6 +166,9 @@ make install
### Testing
+The framework [busted](https://github.com/Olivine-Labs/busted) is used
+for the tests.
+
```
luarocks install busted
busted --exclude-tags=skip test/lua/*.lua
@@ -167,11 +182,14 @@ make test
### Release a new version
+This project uses [semantic versioning](https://semver.org).
+
Update version in:
* luakeys-doc.tex
* luakeys-debug.sty
* luakeys.sty
+* luakeys.lua
Update copyright in:
@@ -185,4 +203,4 @@ Update copyright in:
Summarize the changes in the luakeys-doc.tex as changes.
-Create a new git tag `git tag -sa v0.3`. Prefix the version with “v”.
+Create a new git tag `git tag -sa 0.7.0`.
diff --git a/macros/luatex/generic/luakeys/luakeys-debug.sty b/macros/luatex/generic/luakeys/luakeys-debug.sty
index 7fcb483741..1a26a66450 100644
--- a/macros/luatex/generic/luakeys/luakeys-debug.sty
+++ b/macros/luatex/generic/luakeys/luakeys-debug.sty
@@ -17,6 +17,6 @@
% luakeys-debug.sty and luakeys-debug.tex.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{luakeys-debug}[2022/06/09 v0.6 Debug package for luakeys.]
+\ProvidesPackage{luakeys-debug}[2022/07/06 0.7.0 Debug package for luakeys.]
\input luakeys-debug.tex
diff --git a/macros/luatex/generic/luakeys/luakeys-debug.tex b/macros/luatex/generic/luakeys/luakeys-debug.tex
index e7758cce0a..b78951779b 100644
--- a/macros/luatex/generic/luakeys/luakeys-debug.tex
+++ b/macros/luatex/generic/luakeys/luakeys-debug.tex
@@ -16,50 +16,29 @@
% This work consists of the files luakeys.lua, luakeys.sty, luakeys.tex
% luakeys-debug.sty and luakeys-debug.tex.
-\directlua{
+\directlua
+{
luakeys = require('luakeys')
}
-% https://tex.stackexchange.com/a/418401/42311
-\catcode`\@=11
-\long\def\LuaKeysIfNextChar#1#2#3{%
- \let\@tmpa=#1%
- \def\@tmpb{#2}%
- \def\@tmpc{#3}%
- \futurelet\@future\LuaKeysIfNextChar@i%
-}%
-\def\LuaKeysIfNextChar@i{%
- \ifx\@tmpa\@future%
- \expandafter\@tmpb
- \else
- \expandafter\@tmpc
- \fi
-}%
-\def\luakeysdebug@parse@options#1{
- \directlua{
- luakeys.save(
- 'debug_options',
- luakeys.parse('#1', { format_keys = { 'snake', 'lower' } })
- )
- }
-}%
-\def\luakeysdebug@output#1{
+\def\luakeysdebug%
+{%
+ \directlua%
{
- \tt
- \parindent=0pt
- \directlua{
- local result = luakeys.parse('\luaescapestring{\unexpanded{#1}}', luakeys.get('debug_options'))
- tex.print(luakeys.stringify(result, true))
- luakeys.debug(result)
- }
- }
-}%
-\def\luakeysdebug@oarg[#1]#2{%
- \luakeysdebug@parse@options{#1}%
- \luakeysdebug@output{#2}%
-}%
-\def\luakeysdebug@marg#1{%
- \luakeysdebug@output{#1}%
-}%
-\def\luakeysdebug{\LuaKeysIfNextChar[{\luakeysdebug@oarg}{\luakeysdebug@marg}}%
-\catcode`\@=12
+ local oarg = luakeys.utils.scan_oarg()
+ local marg = token.scan_argument(false)
+ local opts
+ if oarg then
+ opts = luakeys.parse(oarg, { format_keys = { 'snake', 'lower' } })
+ end
+ local result = luakeys.parse(marg, opts)
+ luakeys.debug(result)
+ tex.print(
+ '{' ..
+ '\string\\tt' ..
+ '\string\\parindent=0pt' ..
+ luakeys.stringify(result, true) ..
+ '}'
+ )
+ }%
+}
diff --git a/macros/luatex/generic/luakeys/luakeys-doc.pdf b/macros/luatex/generic/luakeys/luakeys-doc.pdf
index 6fe42295c4..ee0f3411f6 100644
--- a/macros/luatex/generic/luakeys/luakeys-doc.pdf
+++ b/macros/luatex/generic/luakeys/luakeys-doc.pdf
Binary files differ
diff --git a/macros/luatex/generic/luakeys/luakeys-doc.tex b/macros/luatex/generic/luakeys/luakeys-doc.tex
index bc9a55f632..dd6fcc0973 100644
--- a/macros/luatex/generic/luakeys/luakeys-doc.tex
+++ b/macros/luatex/generic/luakeys/luakeys-doc.tex
@@ -1,12 +1,12 @@
\documentclass{ltxdoc}
-\usepackage[hidelinks]{hyperref}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\usepackage{mdframed}
\usepackage{minted}
+\usepackage{luakeys}
\usepackage{luakeys-debug}
\usepackage{multicol}
\usepackage{luacode}
@@ -22,19 +22,30 @@
\def\lua#1{\mintinline{lua}|#1|}
\def\latex#1{\mintinline{latex}|#1|}
-\NewDocumentCommand { \InputLatexExample } { O{} m } {
+\NewDocumentCommand { \InputLatex } { O{} m } {
\begin{mdframed}
\inputminted[linenos=false,#1]{latex}{examples/#2}
\end{mdframed}
}
-\NewDocumentCommand { \InputLuaExample } { O{} m } {
+\NewDocumentCommand { \InputLua } { O{} m } {
\begin{mdframed}
\inputminted[linenos=false,#1]{lua}{examples/#2}
\end{mdframed}
}
\catcode`_=12
+\def\DefaultOpt#1{%
+ \texttt{\directlua{
+ tex.print(luakeys.print_default('opts', '#1'))
+ }}%
+}
+
+\def\DefaultOptDescription#1{
+\noindent
+The default value of the option “\texttt{#1}” is:
+\DefaultOpt{#1}.
+}
\begin{document}
@@ -44,15 +55,16 @@
\author{%
Josef Friedrich\\%
\url{josef@friedrich.rocks}\\%
- \href{https://github.com/Josef-Friedrich/luakeys}{github.com/Josef-Friedrich/luakeys}%
+ \href{https://github.com/Josef-Friedrich/luakeys}
+ {github.com/Josef-Friedrich/luakeys}%
}
-\date{v0.6 from 2022/06/09}
+\date{0.7.0 from 2022/07/06}
\maketitle
\vfill
-\InputLuaExample[firstline=4,lastline=7]{first-page.lua}
+\InputLua[firstline=4,lastline=7]{first-page.lua}
\noindent
Result:
@@ -83,6 +95,7 @@ Result:
\newpage
+% \section{Einführung}
\section{Introduction}
\noindent
@@ -112,20 +125,62 @@ Since |luakeys| uses
\href{http://www.inf.puc-rio.br/~roberto/lpeg/}{LPeg}, the parsing
mechanism should be pretty robust.
+% Der Artikel TUGboat
+% \href{http://www.tug.org/tugboat/tb30-1/tb94wright-keyval.pdf}
+% {“Implementing key–value input: An introduction” (Volume 30 (2009), No.
+% 1)} von \emph{Joseph Wright} und \emph{Christian Feuersänger} gibt einen
+% einen guten Überblick über die verfügbaren Key-Value-Pakete.
The TUGboat article
\href{http://www.tug.org/tugboat/tb30-1/tb94wright-keyval.pdf}
-{“Implementing key–value input: An introduction” (Volume 30 (2009), No. 1)}
-by \emph{Joseph Wright} and \emph{Christian Feuersänger} gives a good
-overview of the available key-value packages.
-
+{“Implementing key–value input: An introduction” (Volume 30 (2009), No.
+1)} by \emph{Joseph Wright} and \emph{Christian Feuersänger} gives a
+good overview of the available key-value packages.
+
+% Dieses Paket wäre ohne den Artikel
+% \href{https://tug.org/TUGboat/tb40-2/tb125menke-lpeg.pdf}
+% {"Parsing complex data formats in LuaTEX with LPEG" (Volume 40 (2019),
+% No. 2)} nicht möglich gewesen.
This package would not be possible without the article
\href{https://tug.org/TUGboat/tb40-2/tb125menke-lpeg.pdf}
-{“Parsing complex data formats in LuaTEX with LPEG” (Volume 40 (2019), No. 2)}.
+{“Parsing complex data formats in LuaTEX with LPEG” (Volume 40 (2019),
+No. 2)}.
+
+\subsection{Pros of \texttt{luakeys}}
+
+\begin{itemize}
+% \item Schlüssel-Wert-Paare können unabhängig vom Makro-Paket (latex or
+% context) analysiert werden.
+\item Key-value pairs can be parsed independently of the macro
+collection (\LaTeX{} or Con\TeX{}t).
+
+% \item Sogar in Plain LuaTex können Schlüssel analysiert werden
+\item Even in plain Lua\TeX{} keys can be parsed.
+
+% \item |luakeys| kann mit ineinander verschachtelten listen an
+% Schlüssel-Wert-Paaren umgehen, d. h. es kann mit einer rekursiven
+% Datenstruktur an Schlüssel umgehen.
+\item |luakeys| can handle nested lists of key-value pairs, i.e. it can
+handle a recursive data structure of keys.
+
+% \item Schlüssel müssen nicht, aber können definiert werden.
+\item Keys do not have to be defined, but can they can be defined.
+\end{itemize}
+
+\subsection{Cons of \texttt{luakeys}}
+
+\begin{itemize}
+% \item Das Packet funktioniert nur in der Verbindung mit Lua\TeX.
+\item The package works only in combination with Lua\TeX.
+
+% \item Du musst zwei Sprachen beherrschen: \TeX{} und Lua.
+\item You need to know two languages: \TeX{} and Lua.
+\end{itemize}
%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------
+% \section{Wie das Paket geladen wird}
\section{How the package is loaded}
%%
@@ -142,7 +197,7 @@ The core functionality of this package is realized in Lua.
So you can use |luakeys| even without using the wrapper files
|luakeys.sty| and |luakeys.tex|.
-\InputLatexExample{loading/lua.tex}
+\InputLatex{loading/lua.tex}
%%
%
@@ -155,8 +210,8 @@ So you can use |luakeys| even without using the wrapper files
For example, the MiK\TeX{} package manager downloads packages only when
needed.
%
-% Es wurde berichtet, dass dieser automatische Download nur mit Hilfe der
-% Hüll-Dateien funktioniert.
+% Es wurde berichtet, dass dieser automatische Download nur mit Hilfe
+% der Hüll-Dateien funktioniert.
It has been reported that this automatic download only works with this
wrapper files.
%
@@ -164,7 +219,7 @@ wrapper files.
% “\latex{\usepackage{luakeys}} ”Ausschau.
Probably MiK\TeX{} is searching for an occurrence of the \LaTeX{} macro
“\latex{\usepackage{luakeys}}”.
-
+%
% Die mitgelieferte Lua\LaTeX{}-Datei ist recht klein:
The supplied Lua\LaTeX{} file is quite small:
@@ -175,38 +230,62 @@ The supplied Lua\LaTeX{} file is quite small:
\end{minted}
\noindent
+% Es lädt das Lua-Modul in die globale Variable \texttt{luakeys}.
It loads the Lua module into the global variable \texttt{luakeys}.
-\InputLatexExample{loading/latex.tex}
+\InputLatex{loading/tex-latex.tex}
%%
%
%%
+% \subsection{Verwendung des Plain-Lua\TeX{}-Hüllpakets
+% \texttt{luakeys.tex}}
\subsection{Using the plain Lua\TeX{} wrapper \texttt{luakeys.tex}}
-Even smaller is the file \texttt{luakeys.tex}. It consists of only one
-line:
+% Noch kleiner ist die Datei \texttt{luakeys.tex}.
+Even smaller is the file \texttt{luakeys.tex}.
+%
+% Sie besteht aus nur einer Zeile:
+It consists of only one line:
\begin{minted}{latex}
\directlua{luakeys = require('luakeys')}
\end{minted}
\noindent
+% Es macht dasselbe wie das Lua\LaTeX{}-Hüllpacket und lädt das
+% Lua-Modul \texttt{luakeys.lua} in die globale Variable
+% \texttt{luakeys}.
It does the same as the Lua\LaTeX{} wrapper and loads the Lua module
\texttt{luakeys.lua} into the global variable \texttt{luakeys}.
-\InputLatexExample{loading/tex.tex}
+\InputLatex{loading/tex-plain.tex}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Lua interface / API}
-To learn more about the individual functions (local functions), please
+% Das Lua-Modul exportiert diese Funktionen und Tabellen:
+The Lua module exports this functions and tables:
+
+\InputLua[firstline=3,lastline=13]{export.lua}
+
+% Diese Dokumentation stellt nur die öffentlichen Funktionen und
+% Tabellen vor.
+This documentation presents only the public functions and tables.
+%
+% Um mehr über die privaten, nicht exportierten Funktionen zu erfahren,
+% lesen Sie bitte die
+% \href{https://josef-friedrich.github.io/luakeys/}{Quellcode
+% Dokumentation}, die mit
+% \href{http://stevedonovan.github.io/ldoc/}{LDoc} erstellt wurde.
+To learn more about the private, not exported functions, please
read the \href{https://josef-friedrich.github.io/luakeys/}{source code
documentation}, which was created with
-\href{http://stevedonovan.github.io/ldoc/}{LDoc}. The Lua module exports
-this functions and tables:
-
-\InputLuaExample[firstline=3,lastline=12]{export.lua}
+\href{http://stevedonovan.github.io/ldoc/}{LDoc}.
\subsection{Lua indentifier names}
@@ -219,7 +298,8 @@ hopefully unambiguous and familiar to external readers.
\begin{tabular}{lll}
Abbreviation & spelled out & Example \\\hline
\lua{kv_string} & Key-value string & \lua{'key=value'} \\
-\lua{opts} & Options (for the parse function) & \lua{ { no_error = false } } \\
+\lua{opts} & Options (for the parse function) &
+\lua{ { no_error = false } } \\
\lua{defs} & Definitions \\
\lua{def} & Definition \\
\lua{attr} & Attributes (of a definition) \\
@@ -233,7 +313,8 @@ These unabbreviated variable names are commonly used.
\begin{tabular}{ll}
\lua{result} &
-% Das Endergebnis aller einzelnen Übersetzungs- und Normalisierungsschritte
+% Das Endergebnis aller einzelnen Übersetzungs- und
+% Normalisierungsschritte
The final result of all individual parsing and normalization steps. \\
\lua{unknown} &
@@ -250,54 +331,41 @@ The raw result of the Lpeg grammar parser. \\
%
%%
-\subsection{Function \texttt{parse(kv_string, opts): result, unknown, raw}}
+\subsection{Function “\texttt{parse(kv_string, opts): result, unknown,
+raw}”}
\label{parse}
% Die Function parse ist die wichtigste Funktion des Pakets.
The function \lua{parse(kv_string, opts)} is the most important function
of the package.
+%
+%
% Sie konvertiert eine Schlüssel-Wert-Zeichenkette in eine Lua Tabelle.
It converts a key-value string into a Lua table.
-\begin{minted}{latex}
-\newcommand{\mykeyvalcmd}[2][]{
- \directlua{
- result = luakeys.parse('#1')
- luakeys.debug(result)
- }
- #2
-}
-\mykeyvalcmd[one=1]{test}
-\end{minted}
+\InputLatex{functions/parse/tex-latex.tex}
\noindent
In plain \TeX:
-\begin{minted}{latex}
-\def\mykeyvalcommand#1{
- \directlua{
- result = luakeys.parse('#1')
- luakeys.debug(result)
- }
-}
-\mykeyvalcmd{one=1}
-\end{minted}
+\InputLatex{functions/parse/tex-plain.tex}
\subsection{Options to configure the \texttt{parse} function}
\noindent
The \lua{parse} function can be called with an options table. This
-options are supported:
+options are supported: \catcode`_=12
+\directlua{luakeys.print_names('opts')}
-\InputLuaExample[firstline=5,lastline=69]{opts/all-opts.lua}
+\InputLua[firstline=5,lastline=69]{opts/all-opts.lua}
\noindent
The options can also be set globally using the exported table
|opts|:
-\InputLuaExample[firstline=4,lastline=4]{opts/exported-default-opts.lua}
+\InputLua[firstline=4,lastline=4]{opts/exported-default-opts.lua}
-\InputLuaExample[firstline=10,lastline=11]{opts/exported-default-opts.lua}
+\InputLua[firstline=10,lastline=11]{opts/exported-default-opts.lua}
%%
%
@@ -305,45 +373,49 @@ The options can also be set globally using the exported table
\subsubsection{Option “\texttt{convert_dimensions}”}
+% Wenn Sie die Option \lua{convert_dimensions} auf \lua{true} setzen,
+% erkennt |luakeys| die \TeX{}-Dimensionen und konvertiert sie mit Hilfe
+% der die Funktion \lua{tex.sp(dim)} in scaled points.
If you set the option \lua{convert_dimensions} to \lua{true}, |luakeys|
detects the \TeX{} dimensions and converts them into scaled points using
the function \lua{tex.sp(dim)}.
-\InputLuaExample[firstline=4,lastline=7]{opts/convert-dimensions.lua}
+\InputLua[firstline=4,lastline=7]{opts/convert-dimensions/true.lua}
\noindent
+% Standardmäßig werden die Dimensionen nicht in skalierte Punkte
+% umgewandelt.
By default the dimensions are not converted into scaled points.
-\InputLuaExample[firstline=13,lastline=18]{opts/convert-dimensions.lua}
+\InputLua[firstline=4,lastline=9]{opts/convert-dimensions/false.lua}
\noindent
-If you want to convert a scale point into a unit string you can use the module
-\href{https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua}{lualibs-util-dim.lua}.
+% Wenn Sie eine skalierte Punktzahl in einen Dimensionszeichenketten
+% umwandeln möchten, können Sie das Modul
+If you want to convert a scaled points number into a dimension string
+you can use the module
+\href{https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua}
+{lualibs-util-dim.lua}.
\begin{minted}{lua}
require('lualibs')
tex.print(number.todimen(tex.sp('1cm'), 'cm', '%0.0F%s'))
\end{minted}
+\DefaultOptDescription{convert_dimensions}
+
%%
%
%%
\subsubsection{Option “\texttt{debug}”}
-If the option “debug” is set to ture, the result table is printed to the
-console.
+% Wenn die Option \lua{debug} auf true gesetzt ist, wird die
+% Ergebnistabelle in der Konsole ausgegeben.
+If the option \lua{debug} is set to ture, the result table is printed to
+the console.
-\begin{minted}{latex}
-\documentclass{article}
-\usepackage{luakeys}
-\begin{document}
-\directlua{
- luakeys.parse('one,two,three', { debug = true })
-}
-debug
-\end{document}
-\end{minted}
+\InputLatex{opts/debug-latex.tex}
\begin{verbatim}
This is LuaHBTeX, Version 1.15.0 (TeX Live 2022)
@@ -361,6 +433,8 @@ local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./debug.aux)
Transcript written on debug.log.
\end{verbatim}
+\DefaultOptDescription{debug}
+
%%
%
%%
@@ -375,13 +449,15 @@ The option \lua{default} can be used to specify which value naked keys
(keys without a value) get. This option has no influence on keys with
values.
-\InputLuaExample[firstline=4,lastline=5]{opts/default.lua}
+\InputLua[firstline=4,lastline=5]{opts/default.lua}
\noindent
% Standardmäßig erhalten nackte Schlüssel den Wert \lua{true}.
By default, naked keys get the value \lua{true}.
-\InputLuaExample[firstline=11,lastline=12]{opts/default.lua}
+\InputLua[firstline=11,lastline=12]{opts/default.lua}
+
+\DefaultOptDescription{default}
%%
%
@@ -402,7 +478,9 @@ The result table is merged into the defaults table.
Values in the defaults table are
overwritten by values in the result table.
-\InputLuaExample[firstline=4,lastline=7]{opts/defaults.lua}
+\InputLua[firstline=4,lastline=7]{opts/defaults.lua}
+
+\DefaultOptDescription{defaults}
%%
%
@@ -421,13 +499,15 @@ If you use the \lua{defs} option, you don't need to call the
% Anstatt
Instead of ...
-\InputLuaExample[firstline=4,lastline=5]{opts/defs.lua}
+\InputLua[firstline=4,lastline=5]{opts/defs.lua}
\noindent
% können wir schreiben ..
we can write ...
-\InputLuaExample[firstline=11,lastline=13]{opts/defs.lua}
+\InputLua[firstline=11,lastline=13]{opts/defs.lua}
+
+\DefaultOptDescription{defs}
%%
%
@@ -438,17 +518,19 @@ we can write ...
\begin{description}
\item[lower] \strut
-\InputLuaExample[firstline=4,lastline=5]{opts/format-keys.lua}
+\InputLua[firstline=4,lastline=5]{opts/format-keys.lua}
\item[snake] \strut
-\InputLuaExample[firstline=11,lastline=12]{opts/format-keys.lua}
+\InputLua[firstline=11,lastline=12]{opts/format-keys.lua}
\item[upper] \strut
-\InputLuaExample[firstline=18,lastline=19]{opts/format-keys.lua}
+\InputLua[firstline=18,lastline=19]{opts/format-keys.lua}
\end{description}
+\DefaultOptDescription{format_keys}
+
%%
%
%%
@@ -463,8 +545,8 @@ processing of the \lua{parse} function.
% Die Funktionen sind in der Verarbeitungsreihenfolge aufgelistet.
The functions are listed in processing order.
%
-% \lua{*_before_opts} bedeutet, dass die Hooks nach der LPeg Syntaxanalyse
-% und vor dem Anwenden der Optionen ausgeführt
+% \lua{*_before_opts} bedeutet, dass die Hooks nach der LPeg
+% Syntaxanalyse und vor dem Anwenden der Optionen ausgeführt
\lua{*_before_opts} means that the hooks are executed after the LPeg
syntax analysis and before the options are applied.
%
@@ -504,7 +586,7 @@ definitions.
The \lua{kv_string} hook is called as the first of the hook functions
before the LPeg syntax parser is executed.
-\InputLuaExample[firstline=4,lastline=11]{hooks/kv-string.lua}
+\InputLua[firstline=4,lastline=11]{hooks/kv-string.lua}
\paragraph{\texttt{keys_*}}
@@ -515,12 +597,12 @@ result table.
% Die Hook-Funktion muss zwei Werte zurückgeben: \lua{key, value}
The hook function must return two values: \lua{key, value}.
%
-% Das folgende Beispiel gibt \lua{key} und \lua{value} unverändert zurück,
-% sodass die Ergebnistabelle nicht verändert wird.
+% Das folgende Beispiel gibt \lua{key} und \lua{value} unverändert
+% zurück, sodass die Ergebnistabelle nicht verändert wird.
The following example returns \lua{key} and \lua{value} unchanged, so
the result table is not changed.
-\InputLuaExample[firstline=4,lastline=11]{hooks/keys-unchanged.lua}
+\InputLua[firstline=4,lastline=11]{hooks/keys-unchanged.lua}
\noindent
% Das nächste Beispiel demonstriert den dritten Parameter \lua{depth}
@@ -528,7 +610,7 @@ the result table is not changed.
The next example demonstrates the third parameter \lua{depth} of the
hook function.
-\InputLuaExample[firstline=4,lastline=16]{hooks/keys-depth.lua}
+\InputLua[firstline=4,lastline=16]{hooks/keys-depth.lua}
\paragraph{\texttt{result_*}}
@@ -549,12 +631,14 @@ as a parameter.
With the help of the option \lua{naked_as_value}, naked keys are not
given a default value, but are stored as values in a Lua table.
-\InputLuaExample[firstline=4,lastline=5]{opts/naked-as-value.lua}
+\InputLua[firstline=4,lastline=5]{opts/naked-as-value.lua}
\noindent
If we set the option \lua{naked_as_value} to \lua{true}:
-\InputLuaExample[firstline=11,lastline=14]{opts/naked-as-value.lua}
+\InputLua[firstline=11,lastline=14]{opts/naked-as-value.lua}
+
+\DefaultOptDescription{naked_as_value}
%%
%
@@ -568,12 +652,14 @@ By default the parse function throws an error if there are unknown keys.
% Mit Hilfe der Option \lua{no_error} kann dies unterbunden werden.
This can be prevented with the help of the \lua{no_error} option.
-\InputLuaExample[firstline=5,lastline=6]{opts/no-error.lua}
+\InputLua[firstline=5,lastline=6]{opts/no-error.lua}
\noindent
If we set the option \lua{no_error} to \lua{true}:
-\InputLuaExample[firstline=9,lastline=10]{opts/no-error.lua}
+\InputLua[firstline=9,lastline=10]{opts/no-error.lua}
+
+\DefaultOptDescription{no_error}
%%
%
@@ -587,15 +673,17 @@ If we set the option \lua{no_error} to \lua{true}:
With the help of the option \lua{unpack}, all tables that consist of
only one a single naked key or a single standalone value are unpacked.
-\InputLuaExample[firstline=4,lastline=5]{opts/unpack.lua}
+\InputLua[firstline=4,lastline=5]{opts/unpack.lua}
+
+\InputLua[firstline=11,lastline=12]{opts/unpack.lua}
-\InputLuaExample[firstline=11,lastline=12]{opts/unpack.lua}
+\DefaultOptDescription{unpack}
%%
%
%%
-\subsection{Function \texttt{define(defs, opts): parse}}
+\subsection{Function “\texttt{define(defs, opts): parse}”}
\label{define}
The \lua{define} function returns a \lua{parse} function (see
@@ -609,13 +697,13 @@ key-value pair is then stored under this key.
\item by the “name” attribute.
\end{enumerate}
-\InputLuaExample[firstline=4,lastline=16]{functions/define.lua}
+\InputLua[firstline=4,lastline=16]{functions/define.lua}
\noindent
For nested definitions, only the last two ways of specifying the key
names can be used.
-\InputLuaExample[firstline=26,lastline=33]{functions/define.lua}
+\InputLua[firstline=26,lastline=33]{functions/define.lua}
%-----------------------------------------------------------------------
%
@@ -636,12 +724,16 @@ The name \emph{“attribute”} for an option, a key, a property ... (to
list just a few naming possibilities) to define keys, was deliberately
chosen to distinguish them from the options of the \lua{parse} function.
%
+% Diese Attribute sind erlaubt.
+These attributes are allowed:
+\directlua{luakeys.print_names('attrs')}.
+%
% Das folgende Codebeispiel listet alle Attribute auf, die verwendet
% werden können, um Schlüssel-Wert-Paare zu definieren.
The code example below lists all the attributes that can be used to
define key-value pairs.
-\InputLuaExample[firstline=5,lastline=41]{defs/all-attrs.lua}
+\InputLua[firstline=5,lastline=46]{defs/all-attrs.lua}
%%
%
@@ -653,12 +745,12 @@ With the help of the \lua{alias} attribute, other key names can be used.
The value is always stored under the original key name. A single alias
name can be specified by a string ...
-\InputLuaExample[firstline=4,lastline=7]{defs/attrs/alias.lua}
+\InputLua[firstline=4,lastline=7]{defs/attrs/alias.lua}
\noindent
multiple aliases by a list of strings.
-\InputLuaExample[firstline=13,lastline=16]{defs/attrs/alias.lua}
+\InputLua[firstline=13,lastline=16]{defs/attrs/alias.lua}
%%
%
@@ -669,7 +761,7 @@ multiple aliases by a list of strings.
% Die Option \lua{default} wird nur bei nackten Schlüsseln verwendet.
The \lua{default} attribute is used only for naked keys.
-\InputLuaExample[firstline=4,lastline=5]{defs/attrs/always-present.lua}
+\InputLua[firstline=4,lastline=5]{defs/attrs/always-present.lua}
\noindent
% Wird die Option \lua{always_present} auf wahr gesetzt, wird der
@@ -678,7 +770,7 @@ If the attribute \lua{always_present} is set to true, the key is always
included in the result. If no default value is definied, true is taken
as the value.
-\InputLuaExample[firstline=11,lastline=12]{defs/attrs/always-present.lua}
+\InputLua[firstline=11,lastline=12]{defs/attrs/always-present.lua}
%%
%
@@ -690,14 +782,14 @@ as the value.
Some key values should be selected from a restricted set of choices.
These can be handled by passing an array table containing choices.
-\InputLuaExample[firstline=4,lastline=5]{defs/attrs/choices.lua}
+\InputLua[firstline=4,lastline=5]{defs/attrs/choices.lua}
\noindent
When the key-value pair is parsed, values will be checked, and an error
message will be displayed if the value was not one of the acceptable
choices:
-\InputLuaExample[firstline=13,lastline=15]{defs/attrs/choices.lua}
+\InputLua[firstline=13,lastline=15]{defs/attrs/choices.lua}
%%
%
@@ -727,8 +819,8 @@ A type conversion can fail with the three data types
% Dann wird eine Fehlermeldung ausgegeben.
Then an error message is displayed.
-\InputLuaExample[firstline=4,lastline=8]{defs/attrs/data-type.lua}
-\InputLuaExample[firstline=11,lastline=15]{defs/attrs/data-type.lua}
+\InputLua[firstline=4,lastline=8]{defs/attrs/data-type.lua}
+\InputLua[firstline=11,lastline=15]{defs/attrs/data-type.lua}
%%
%
@@ -746,7 +838,7 @@ key individually.
With the global \lua{default} attribute (\ref{option-default}) a default
value can be specified for all naked keys.
-\InputLuaExample[firstline=4,lastline=9]{defs/attrs/default.lua}
+\InputLua[firstline=4,lastline=9]{defs/attrs/default.lua}
%%
%
@@ -766,14 +858,15 @@ Only one key from this group is allowed.
% Wert verwendet werden.
Any value can be used as a name for this exclusive group.
-\InputLuaExample[firstline=4,lastline=9]{defs/attrs/exclusive-group.lua}
+\InputLua[firstline=4,lastline=9]{defs/attrs/exclusive-group.lua}
+\noindent
% Werden mehrer Schlüssel der Gruppe angegeben, so wird eine
% Fehlermeldung geworfen.
If more than one key of the group is specified, an error message is
thrown.
-\InputLuaExample[firstline=21,lastline=23]{defs/attrs/exclusive-group.lua}
+\InputLua[firstline=21,lastline=23]{defs/attrs/exclusive-group.lua}
%%
%
@@ -809,13 +902,13 @@ opposite key pair.
If the key \lua{show} is parsed by the \lua{parse} function, then the
target key \lua{visibility} receives the value \lua{true}.
-\InputLuaExample[firstline=4,lastline=7]{defs/attrs/opposite-keys.lua}
+\InputLua[firstline=4,lastline=7]{defs/attrs/opposite-keys.lua}
% Wird der Schlüssel \lua{hide} gelesen, dann \lua{falsch}.
\noindent
If the key \lua{hide} is parsed, then \lua{false}.
-\InputLuaExample[firstline=13,lastline=13]{defs/attrs/opposite-keys.lua}
+\InputLua[firstline=13,lastline=13]{defs/attrs/opposite-keys.lua}
%%
%
@@ -844,21 +937,31 @@ parse('key=value')
\subsubsection{Attribute “\texttt{match}”}
-% Der Wert des Schlüssel wird der Lua Funktion übergeben
-The value of the key is passed to the Lua function
-\lua{string.match(value, match)} ((\url{http://www.lua.org/manual/5.3/manual.html#pdf-string.match})).
+% Der Wert des Schlüssel wird zuerst der Lua Funktion
+% \lua{string.match(value, match)} übergeben, bevor er dem Schlüssel
+% zugewiesen wird.
+The value of the key is first passed to the Lua function
+\lua{string.match(value, match)}
+(\url{http://www.lua.org/manual/5.3/manual.html#pdf-string.match})
+before being assigned to the key.
+%
+% Du kannst das Attribut \lua{match} deshalb mit einer Pattern-Matching-
+% Zeichenkette konfigurieren, wie sie in Lua zu Einsatz kommt.
+You can therefore configure the \lua{match} attribute with a pattern
+matching string used in Lua.
+%
% Werfe einen Blick in das Lua-Handbuch, wie man Patterns schreibt.
Take a look at the Lua manual on how to write patterns
-(\url{http://www.lua.org/manual/5.3/manual.html#6.4.1})
+(\url{http://www.lua.org/manual/5.3/manual.html#6.4.1}).
-\InputLuaExample[firstline=4,lastline=6]{defs/attrs/match.lua}
+\InputLua[firstline=4,lastline=7]{defs/attrs/match/birthday.lua}
\noindent
% Kann das Pattern im Wert nicht gefunden werden, wird eine
% Fehlermeldung ausgegeben.
If the pattern cannot be found in the value, an error message is issued.
-\InputLuaExample[firstline=14,lastline=17]{defs/attrs/match.lua}
+\InputLua[firstline=15,lastline=18]{defs/attrs/match/birthday.lua}
\noindent
% Der Schlüssel erhält das Ergebnis der Funktion \lua{string.match(value,
@@ -867,8 +970,11 @@ If the pattern cannot be found in the value, an error message is issued.
The key receives the result of the function \lua{string.match(value,
match)}, which means that the original value may not be stored
completely in the key.
+%
+% Im nächsten Beispiel wird der gesamte Eingabewert akzeptiert:
+In the next example, the entire input value is accepted:
-\InputLuaExample[firstline=22,lastline=23]{defs/attrs/match.lua}
+\InputLua[firstline=4,lastline=5]{defs/attrs/match/year.lua}
\noindent
% Das Präfix “waste ” und das Suffix “ rubbisch” der Zeichenketten wird
@@ -876,7 +982,7 @@ completely in the key.
The prefix “waste ” and the suffix “ rubbisch” of the string are
discarded.
-\InputLuaExample[firstline=29,lastline=29]{defs/attrs/match.lua}
+\InputLua[firstline=11,lastline=11]{defs/attrs/match/year.lua}
\noindent
% Da Funktion \lua{string.match(value, match)} immer eine Zeichenkette
@@ -897,13 +1003,61 @@ The \lua{name} attribute allows an alternative notation of key names.
% Anstatt ...
Instead of ...
-\InputLuaExample[firstline=4,lastline=5]{defs/attrs/name.lua}
+\InputLua[firstline=4,lastline=8]{defs/attrs/name/as-key.lua}
\noindent
% ... können wir schreiben:
... we can write:
-\InputLuaExample[firstline=11,lastline=15]{defs/attrs/name.lua}
+\InputLua[firstline=4,lastline=8]{defs/attrs/name/name-attr.lua}
+
+%%
+%
+%%
+
+\subsubsection{Attribute “\texttt{pick}”}
+
+% Das Attribut \lua{pick} sucht nach einem Wert, der keinem Schlüssel
+% zugeordnet ist.
+The attribute \lua{pick} searches for a value not assigned to a key.
+% Der zuerst gefundene Wert, d. h. der weiter links stehende Wert, wird
+% einem Schlüssel zugewiesen.
+The first value found, i.e. the one further to the left, is assigned to
+a key.
+
+\InputLua[firstline=4,lastline=6]{defs/attrs/pick/dimension.lua}
+
+\noindent
+% Es wird nur in der aktuellen Ergebnistabelle gesucht und nicht auf
+% anderen Ebenen in der rekursiven Datenstruktur.
+Only the current result table is searched, not other levels in the
+recursive data structure.
+
+\InputLua[firstline=4,lastline=11]{defs/attrs/pick/different-levels.lua}
+
+\noindent
+% Die Suche nach Werte wird aktiviert, wenn das Attribut \lua{pick} auf
+% \lua{true} gesetzt wird.
+The search for values is activated when the attribute \lua{pick} is set
+to \lua{true}.
+% Die Suche kann eingeschränkt werden, indem ein Datentype angegeben
+% wird.
+The search can be limited by specifying a data type.
+% Nach diesen Datentypen kann gesucht werden:
+These data types can be searched for:
+\directlua{
+ local types = {}
+ for t, fn in pairs(luakeys.is) do
+ table.insert(types, t)
+ end
+ tex.print(table.concat(types, ', '))
+}.
+
+% Wird einem Schlüssel bereits bei der Eingabe ein Wert zugewiesen, dann
+% wird nicht weiter nach Werten gesucht.
+If a value is already assigned to a key when it is entered, then no
+further search for values is performed.
+\InputLua[firstline=4,lastline=8]{defs/attrs/pick/value-set.lua}
%%
%
@@ -912,19 +1066,24 @@ Instead of ...
\subsubsection{Attribute “\texttt{process}”}
\label{attr-process}
-The \lua{process} attribute can be used to define a function whose return
-value is passed to the key. Four parameters are passed when the
-function is called:
+% Das Attribut \lua{process} kann dazu verwendet werden, um eine Funktion
+% zu definieren, deren Rückgabewert an den Schlüssel übergeben wird.
+The \lua{process} attribute can be used to define a function whose
+return value is passed to the key.
+%
+% Beim Aufruf der Funktion werden vier Parameter übergeben:
+Four parameters are passed when the function is called:
\begin{enumerate}
\item \lua{value}:
-% Der zum schlüssel gehörende aktuelle Wert.
+% Der zum Schlüssel gehörende aktuelle Wert.
The current value asssociated with the key.
\item \lua{input}:
% Die Ergebnis-Tabelle, die vor dem Zeitpunkt geklont wurde, als mit dem
% Anwenden der Definitionen begonnen wurde.
-The result table cloned before the time the definitions started to be applied.
+The result table cloned before the time the definitions started to be
+applied.
\item \lua{result}: The table in which the final result will be saved.
@@ -932,26 +1091,29 @@ The result table cloned before the time the definitions started to be applied.
are stored.
\end{enumerate}
-% Das folgende Beispiel demonstriert den Parameter \lua{value}.
\noindent
+% Das folgende Beispiel demonstriert den Parameter \lua{value}:
The following example demonstrates the \lua{value} parameter:
-\InputLuaExample[firstline=4,lastline=14]{defs/attrs/process.lua}
+\InputLua[firstline=4,lastline=14]{defs/attrs/process/parameter-value.lua}
\noindent
+% Das folgende Beispiel demonstriert den Parameter \lua{input}:
The following example demonstrates the \lua{input} parameter:
-\InputLuaExample[firstline=22,lastline=34]{defs/attrs/process.lua}
+\InputLua[firstline=4,lastline=16]{defs/attrs/process/parameter-input.lua}
\noindent
+% Das folgende Beispiel demonstriert den Parameter \lua{result}:
The following example demonstrates the \lua{result} parameter:
-\InputLuaExample[firstline=42,lastline=50]{defs/attrs/process.lua}
+\InputLua[firstline=4,lastline=12]{defs/attrs/process/parameter-result.lua}
\noindent
+% Das folgende Beispiel demonstriert den Parameter \lua{unknown}:
The following example demonstrates the \lua{unknown} parameter:
-\InputLuaExample[firstline=58,lastline=65]{defs/attrs/process.lua}
-\InputLuaExample[firstline=69,lastline=69]{defs/attrs/process.lua}
+\InputLua[firstline=4,lastline=11]{defs/attrs/process/parameter-unknown.lua}
+\InputLua[firstline=15,lastline=15]{defs/attrs/process/parameter-unknown.lua}
%%
%
@@ -959,16 +1121,41 @@ The following example demonstrates the \lua{unknown} parameter:
\subsubsection{Attribute “\texttt{required}”}
-\InputLuaExample[firstline=4,lastline=5]{defs/attrs/required.lua}
+% Durch das Attribut \lua{required} kann erzwungen werden, dass ein
+% bestimmter Schlüssel angegeben werden muss.
+The \lua{required} attribute can be used to enforce that a specific key
+must be specified.
+%
+% Im untenstehenden Beispiel wird der Schlüssel \lua{important} als
+% zwingend notwendig definiert.
+In the example below, the key \lua{important} is defined as mandatory.
-\InputLuaExample[firstline=13,lastline=14]{defs/attrs/required.lua}
+\InputLua[firstline=4,lastline=5]{defs/attrs/required.lua}
+
+\noindent
+% Fehlt der Schlüssel \lua{important} in der Eingabe, so tritt eine
+% Fehlermeldung auf.
+If the key \lua{important} is missing in the input, an error message
+occurs.
+
+\InputLua[firstline=13,lastline=14]{defs/attrs/required.lua}
\noindent
A recursive example:
-\InputLuaExample[firstline=18,lastline=23]{defs/attrs/required.lua}
-\InputLuaExample[firstline=29,lastline=30]{defs/attrs/required.lua}
-\InputLuaExample[firstline=38,lastline=39]{defs/attrs/required.lua}
+\InputLua[firstline=18,lastline=23]{defs/attrs/required.lua}
+
+\noindent
+% Der Schlüssel \lua{important2} auf der Ebene 2 fehlt.
+The \lua{important2} key on level 2 is missing.
+
+\InputLua[firstline=29,lastline=30]{defs/attrs/required.lua}
+
+\noindent
+% Der Schlüssel \lua{important1} auf der untersten Schlüssel-Ebene fehlt.
+The \lua{important1} key at the lowest key level is missing.
+
+\InputLua[firstline=38,lastline=39]{defs/attrs/required.lua}
%%
%
@@ -981,39 +1168,39 @@ A recursive example:
The \lua{sub_keys} attribute can be used to build nested key-value pair
definitions.
-\InputLuaExample[firstline=4,lastline=16]{defs/attrs/sub-keys.lua}
+\InputLua[firstline=4,lastline=16]{defs/attrs/sub-keys.lua}
%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------
-\subsection{Function \texttt{render(result): string}}
+\subsection{Function “\texttt{render(result): string}”}
The function \lua{render(result)} reverses the function
\lua{parse(kv_string)}. It takes a Lua table and converts this table
into a key-value string. The resulting string usually has a different
order as the input table.
-\InputLuaExample[firstline=4,lastline=10]{functions/render.lua}
+\InputLua[firstline=4,lastline=10]{functions/render.lua}
\noindent
In Lua only tables with 1-based consecutive integer keys (a.k.a. array
tables) can be parsed in order.
-\InputLuaExample[firstline=16,lastline=17]{functions/render.lua}
+\InputLua[firstline=16,lastline=17]{functions/render.lua}
%%
%
%%
-\subsection{Function \texttt{debug(result): void}}
+\subsection{Function “\texttt{debug(result): void}”}
The function \lua{debug(result)} pretty prints a Lua table to standard
output (stdout). It is a utility function that can be used to debug and
inspect the resulting Lua table of the function \lua{parse}. You have to
compile your \TeX{} document in a console to see the terminal output.
-\InputLuaExample[firstline=4,lastline=5]{functions/debug.lua}
+\InputLua[firstline=4,lastline=5]{functions/debug.lua}
\noindent
The output should look like this:
@@ -1032,7 +1219,7 @@ The output should look like this:
%
%%
-\subsection{Function \texttt{save(identifier, result): void}}
+\subsection{Function “\texttt{save(identifier, result): void}”}
The function \lua{save(identifier, result)} saves a result (a
table from a previous run of \lua{parse}) under an identifier.
@@ -1043,7 +1230,7 @@ store results for the later usage.
%
%%
-\subsection{Function \texttt{get(identifier): result}}
+\subsection{Function “\texttt{get(identifier): result}”}
The function \lua{get(identifier)} retrieves a saved result from the
result store.
@@ -1052,22 +1239,105 @@ result store.
%
%%
-\subsection{Table \texttt{is}}
+\subsection{Table “\texttt{is}”}
+
+% In der Tabelle \lua{is} werden einige Funktionen zusammengefasst, die
+% überprüft ob eine Eingabe einem bestimmen Datentyp entspricht.
+In the table \lua{is} some functions are summarized, which check whether
+an input corresponds to a certain data type.
+%
+% Alle Funktionen akzeptieren nicht nur die entsprechenden Lua-Datentypen,
+% sondern auch Eingaben als Zeichenketten.
+All functions accept not only the corresponding Lua data types, but also
+input as strings.
+%
+% Beispielsweise wird die Zeichenkette \lua{'true'} von der
+% \lua{is.boolean()}-Funktion als Wahrheitswert erkannt.
+For example, the string \lua{'true'} is recognized by the
+\lua{is.boolean()} function as a boolean value.
+
+\subsubsection{Function “\texttt{is.boolean(value): boolean}”}
+\InputLua[firstline=6,lastline=23]{functions/is/boolean.lua}
+
+\subsubsection{Function “\texttt{is.dimension(value): boolean}”}
+\InputLua[firstline=6,lastline=16]{functions/is/dimension.lua}
+
+\subsubsection{Function “\texttt{is.integer(value): boolean}”}
+\InputLua[firstline=6,lastline=11]{functions/is/integer.lua}
+
+\subsubsection{Function “\texttt{is.number(value): boolean}”}
+\InputLua[firstline=6,lastline=13]{functions/is/number.lua}
+
+\subsubsection{Function “\texttt{is.string(value): boolean}”}
+\InputLua[firstline=6,lastline=12]{functions/is/string.lua}
+
+%%
+%
+%%
+
+\subsection{Table “\texttt{utils}”}
+
+\subsubsection{Function “\texttt{utils.scan_oarg(initial_delimiter?, end_delimiter?): string}”}
-\subsubsection{Function \texttt{is.boolean(value): boolean}}
-\InputLuaExample[firstline=7,lastline=23]{is-table.lua}
+% Plain \TeX{} kennt keine optionalen Argumente (oarg).
+Plain \TeX{} does not know optional arguments (oarg).
+%
+% Die Funktion ermöglicht es nicht nur in \LaTeX{}, sondern auch in
+% Plain \TeX{} nach optionalen Argumenten zu suchen.
+The function \\ \lua{utils.scan_oarg(initial_delimiter?,
+end_delimiter?): string} allows to search for optional arguments not only
+in \LaTeX{} but also in Plain \TeX.
+%
+% Die Funktion basiert auf der Token-Bibliothek.
+The function uses the token library built into Lua\TeX{}.
+%
+% Die beiden Parameter \lua{initial_delimiter} und \lua{end_delimiter}
+% können weggelassen werden.
+The two parameters \lua{initial_delimiter} and \lua{end_delimiter} can
+be omitted.
+%
+% Dann werden eckige Klammern als Begrenzungszeichen angenommen.
+Then square brackets are assumed to be delimiters.
+%
+% Dieser Lua-Code \lua{utils.scan_oarg('(', ')')} sucht beispielsweise
+% nach an einem optionalen Argument in runden Klammern.
+For example, this Lua code \lua{utils.scan_oarg('(', ')')} searches for
+an optional argument in round brackets
+%
+% Die Funktion gibt die Zeichenkette zwischen den Begrenzungszeichen
+% zurück, oder nil wenn Begrenzungszeichen gefunden werden konnten.
+The function returns the string between the delimiters or \lua{nil} if
+no delimiters could be found.
+%
+% Die Begrenzungszeichen sind im Ergebnis nicht enthalten.
+The delimiters themselves are not included in the result.
+%
+% Nach dem \latex{\directlua{}} darf das Makro, indem
+% \lua{utils.scan_oarg} eingesetzt wird, zu keinen Zeichen expandieren.
+After the \latex{\directlua{}}, the macro using \lua{utils.scan_oarg}
+must not expand to any characters.
-\subsubsection{Function \texttt{is.dimension(value): boolean}}
-\InputLuaExample[firstline=27,lastline=37]{is-table.lua}
+\InputLatex{utils/scan-oarg-plain.tex}
-\subsubsection{Function \texttt{is.integer(value): boolean}}
-\InputLuaExample[firstline=41,lastline=46]{is-table.lua}
+%%
+%
+%%
+
+\subsection{Table “version”}
-\subsubsection{Function \texttt{is.number(value): boolean}}
-\InputLuaExample[firstline=50,lastline=57]{is-table.lua}
+% Das luakeys Projekt verwendet semantic versioning
+The luakeys project uses semantic versioning.
+% Die drei Versionenzahlen des Semantic Versioning Schemas werden in
+% einer Tabelle in der Reihenfolge MAJOR, MINOR, PATCH als Ganzzahlen
+% abgelegt.
+The three version numbers of the semantic versioning scheme are stored
+in a table as integers in the order MAJOR, MINOR, PATCH.
+% Mit Hilfe dieser Tabelle kann überprüft werden, ob die richtige
+% Version installiert ist.
+This table can be used to check whether the correct version is
+installed.
-\subsubsection{Function \texttt{is.string(value): boolean}}
-\InputLuaExample[firstline=61,lastline=67]{is-table.lua}
+\InputLua[firstline=4,lastline=10]{version.lua}
%-----------------------------------------------------------------------
%
@@ -1128,10 +1398,12 @@ key-value lists (\texttt{level1=\{level2=\{key=value,naked\}\}}).
\alt `ex' | `EX'
\alt `in' | `IN'
\alt `mm' | `MM'
+ \alt `mu' | `MU'
\alt `nc' | `NC'
\alt `nd' | `ND'
\alt `pc' | `PC'
\alt `pt' | `PT'
+ \alt `px' | `PX'
\alt `sp' | `SP'
<boolean> ::= <boolean-true> | <boolean-false>
@@ -1156,16 +1428,10 @@ into Lua’s boolean type \lua{true}, the strings \texttt{false},
\texttt{FALSE} and \texttt{False} into \lua{false}.
\begin{multicols}{2}
-\begin{minted}{latex}
-\luakeysdebug{
- lower case true = true,
- upper case true = TRUE,
- title case true = True
- lower case false = false,
- upper case false = FALSE,
- title case false = False,
-}
-\end{minted}
+\InputLatex[firstline=5,lastline=12]{luakeysdebug/boolean-latex.tex}
+
+\columnbreak
+
\begin{minted}{lua}
{
['lower case true'] = true,
@@ -1185,18 +1451,19 @@ into Lua’s boolean type \lua{true}, the strings \texttt{false},
\subsubsection{number}
\begin{multicols}{2}
-\begin{minted}{latex}
-\luakeysdebug{
- num1 = 4,
- num2 = -4,
- num3 = 0.4
-}
-\end{minted}
+\InputLatex[firstline=5,lastline=13]{luakeysdebug/number-latex.tex}
+
+\columnbreak
+
\begin{minted}{lua}
{
- ['num1'] = 4,
- ['num2'] = -4,
- ['num3'] = 0.4
+ ['num0'] = 42,
+ ['num1'] = 42,
+ ['num2'] = -42,
+ ['num3'] = 4.2,
+ ['num4'] = 0.42,
+ ['num5'] = 0.42,
+ ['num6'] = '0 . 42', -- string
}
\end{minted}
\end{multicols}
@@ -1207,6 +1474,22 @@ into Lua’s boolean type \lua{true}, the strings \texttt{false},
\subsubsection{dimension}
+% Luakeys versucht alle Einheiten zu erkennen, die in der TeX-Welt
+% verwendet werden.
+|luakeys| tries to recognize all units used in the \TeX{} world.
+%
+% Nach dem Lua\TeX-Quellcode .
+According to the Lua\TeX{} source code
+(\href{https://github.com/TeX-Live/luatex/blob/51db1985f5500dafd2393aa2e403fefa57d3cb76/source/texk/web2c/luatexdir/lua/ltexlib.c#L434-L625}
+{source/texk/web2c/luatexdir/lua/ltexlib.c})
+%
+% und nach dem Dimensionen-Modul der lulibs-Bibliothek
+and the dimension module of the lualibs library
+(\href{https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua}
+{lualibs-util-dim.lua}),
+%
+% müssten alle Einheiten erkannt werden
+all units should be recognized.
\begin{multicols}{3}
\tiny
\begin{center}
@@ -1221,33 +1504,19 @@ em & horizontal measure of \emph{M} \\
ex & vertical measure of \emph{x} \\
in & inch \\
mm & milimeter \\
+mu & math unit \\
nc & new cicero \\
nd & new didot \\
pc & pica \\
pt & point \\
+px & x height current font \\
sp & scaledpoint \\
\end{tabular}
\end{center}
\columnbreak
-\begin{minted}{latex}
-\luakeysdebug{
- bp = 1bp,
- cc = 1cc,
- cm = 1cm,
- dd = 1dd,
- em = 1em,
- ex = 1ex,
- in = 1in,
- mm = 1mm,
- nc = 1nc,
- nd = 1nd,
- pc = 1pc,
- pt = 1pt,
- sp = 1sp,
-}
-\end{minted}
+\InputLatex[firstline=5,lastline=21]{luakeysdebug/dimension/all-latex.tex}
\columnbreak
@@ -1261,15 +1530,39 @@ sp & scaledpoint \\
['ex'] = 282460,
['in'] = 4736286,
['mm'] = 186467,
+ ['mu'] = 65536,
['nc'] = 839105,
['nd'] = 69925,
['pc'] = 786432,
['pt'] = 65536,
+ ['px'] = 65781,
['sp'] = 1,
}
\end{minted}
\end{multicols}
+\noindent
+% Im nächsten Beispiel werden die unterschiedlichen Notationsformen der
+% Dimensionen illustriert.
+The next example illustrates the different notations of the dimensions.
+
+\begin{multicols}{2}
+\InputLatex[firstline=5,lastline=12]{luakeysdebug/dimension/notations-latex.tex}
+
+\columnbreak
+
+\begin{minted}{lua}
+{
+ ['upper'] = 1864679,
+ ['lower'] = 1864679,
+ ['space'] = 1864679,
+ ['plus'] = 1864679,
+ ['minus'] = -1864679,
+ ['nodim'] = '1 c m', -- string
+}
+\end{minted}
+\end{multicols}
+
%%
%
%%
@@ -1287,7 +1580,7 @@ With or without double quotes.
If the text have to contain commas, curly braces or equal signs, then
double quotes must be used.
-\InputLuaExample[firstline=4,lastline=17]{data-types/string.lua}
+\InputLua[firstline=4,lastline=17]{data-types/string.lua}
\subsubsection{Naked keys}
@@ -1303,14 +1596,14 @@ and stored into an array.
% Index ist 1).
In Lua an array is a table with numeric indexes (The first index is 1).
-\InputLatexExample[firstline=5,lastline=12]{luakeysdebug/naked-keys.tex}
+\InputLatex[firstline=5,lastline=12]{luakeysdebug/naked-keys-latex.tex}
\noindent
% VAlle erkannten Datentypen können als eigenständige Werte verwendet
% werden.
All recognized data types can be used as standalone values.
-\InputLatexExample[firstline=14,lastline=19]{luakeysdebug/naked-keys.tex}
+\InputLatex[firstline=14,lastline=19]{luakeysdebug/naked-keys-latex.tex}
%-----------------------------------------------------------------------
%
@@ -1320,6 +1613,10 @@ All recognized data types can be used as standalone values.
\section{Examples}
+%%
+%
+%%
+
\subsection{Extend and modify keys of existing macros}
Extend the includegraphics macro with a new key named \latex{caption}
@@ -1327,17 +1624,34 @@ and change the accepted values of the \latex{width} key. A number
between 0 and 1 is allowed and converted into
\latex{width=0.5\linewidth}
-\InputLuaExample{extend-includegraphics/extend-keys.lua}
-\InputLatexExample{extend-includegraphics/extend-keys.tex}
+\InputLua{extend-includegraphics/extend-keys.lua}
+\InputLatex{extend-includegraphics/extend-keys-latex.tex}
+
+%%
+%
+%%
\subsection{Process document class options}
-\begin{minted}{latex}
-\directlua{luakeys.parse('\@classoptionslist')}
-\end{minted}
+% Auf die Optionen einer \LaTeX{} Dokumentenklasse kann über das Macro
+% \latex{\@classoptionslist} zu gegriffen werden.
+The options of a \LaTeX{} document class can be accessed via the
+\latex{\@classoptionslist} macro.
+%
+% Die Zeichenkette des Makros \latex{\@classoptionslist} ist bereits
+% expandiert und normalisiert.
+The string of the macro \latex{\@classoptionslist} is already expanded
+and normalized.
+%
+% Neben Leerzeichen werden auch die geschweiften Klammern entfernt.
+In addition to spaces, the curly brackets are also removed.
+% Es ist deshalb nicht möglich, in einander geschachtelte hierarische
+% Schlüssel-Wert-Paare über die Option zu verarbeiten.
+It is therefore not possible to process nested hierarchical key-value
+pairs via the option.
-\InputLatexExample{class-options/test-class.cls}
-\InputLatexExample{class-options/use-test-class.tex}
+\InputLatex{class-options/test-class.cls}
+\InputLatex{class-options/use-test-class-latex.tex}
\begin{minted}{lua}
{
@@ -1458,30 +1772,30 @@ An example of how to use the command in \LaTeX:
\inputminted[linenos=true]{latex}{luakeys-debug.sty}
-\changes{v0.1}{2021/01/18}{Inital release}
-\changes{v0.2}{2021/09/19}{
+\changes{0.1.0}{2021/01/18}{Inital release}
+\changes{0.2.0}{2021/09/19}{
* Allow all recognized data types as keys
* Allow TeX macros in the values
* New public Lua functions: save(identifier, result), get(identifier)
}
-\changes{v0.3}{2021/11/05}{
+\changes{0.3.0}{2021/11/05}{
* Add a LuaLaTeX wrapper “luakeys.sty”
* Add a plain LuaTeX wrapper “luakeys.tex”
* Rename the previous documentation file “luakeys.tex” to luakeys-doc.tex”
}
-\changes{v0.4}{2021/12/31}{
+\changes{0.4.0}{2021/12/31}{
* Parser: Add support for nested tables (for example {{'a', 'b'}})
* Parser: Allow only strings and numbers as keys
* Parser: Remove support from Lua numbers with exponents (for example '5e+20')
* Switch the Lua testing framework to busted
}
-\changes{v0.5}{2022/04/04}{
+\changes{0.5.0}{2022/04/04}{
* Add possibility to change options globally
* New option: standalone_as_true
* Add a recursive converter callback / hook to process the parse tree
* New option: case_insensitive_keys
}
-\changes{v0.6}{2022/06/09}{
+\changes{0.6.0}{2022/06/09}{
* New feature: keys now can be defined using the function
“define(defs, opts)” or “define(kv_string, { defs = { key = { ... } } })”
* Rename the global options table from “default_options” to “opts”
@@ -1494,6 +1808,14 @@ An example of how to use the command in \LaTeX:
produce the previous effect.
* The function “print()” is now called “debug()”
}
+\changes{0.7.0}{2022/07/06}{
+* The project now uses semantic versioning.
+* New definition attribute “pick” to pick standalone values and assign
+ them to a key
+* New function “utils.scan_oarg()” to search for an optional argument,
+ that means scan for tokens that are enclosed in square brackets
+* extend and improve documentation
+}
\pagebreak
\PrintChanges
\pagebreak
diff --git a/macros/luatex/generic/luakeys/luakeys.lua b/macros/luatex/generic/luakeys/luakeys.lua
index ae689d02c1..3221fc3efd 100644
--- a/macros/luatex/generic/luakeys/luakeys.lua
+++ b/macros/luatex/generic/luakeys/luakeys.lua
@@ -36,13 +36,59 @@ if not token then
}
end
+--- Merge two tables in the first specified table.
+--- The `merge_tables` function copies all keys from the `source` table
+--- to a target table. It returns the modified target table.
+---
+---@see https://stackoverflow.com/a/1283608/10193818
+---
+---@param target table
+---@param source table
+---
+---@return table target The modified target table.
+local function merge_tables(target, source)
+ for key, value in pairs(source) do
+ if type(value) == 'table' then
+ if type(target[key] or false) == 'table' then
+ merge_tables(target[key] or {}, source[key] or {})
+ elseif target[key] == nil then
+ target[key] = value
+ end
+ elseif target[key] == nil then
+ target[key] = value
+ end
+ end
+ return target
+end
+
+---Clone a table.
+---
+---@see http://lua-users.org/wiki/CopyTable
+---
+---@param orig table
+---
+---@return table
+local function clone_table(orig)
+ local orig_type = type(orig)
+ local copy
+ if orig_type == 'table' then
+ copy = {}
+ for orig_key, orig_value in next, orig, nil do
+ copy[clone_table(orig_key)] = clone_table(orig_value)
+ end
+ setmetatable(copy, clone_table(getmetatable(orig)))
+ else -- number, string, boolean, etc
+ copy = orig
+ end
+ return copy
+end
+
local utils = {
--- Get the size of an array like table `{ 'one', 'two', 'three' }` = 3.
- --
- -- @tparam table value A table or any input.
- --
- -- @treturn number The size of the array like table. 0 if the input is
- -- no table or the table is empty.
+ ---
+ ---@param value table # A table or any input.
+ ---
+ ---@return number # The size of the array like table. 0 if the input is no table or the table is empty.
get_array_size = function(value)
local count = 0
if type(value) == 'table' then
@@ -53,12 +99,11 @@ local utils = {
return count
end,
- --- Get the size of a table `{ one = 'one', 'two', 'three' }` = 3.
- --
- -- @tparam table value A table or any input.
- --
- -- @treturn number The size of the array like table. 0 if the input is
- -- no table or the table is empty.
+ ---Get the size of a table `{ one = 'one', 'two', 'three' }` = 3.
+ ---
+ ---@param value table|any # A table or any input.
+ ---
+ ---@return number # The size of the array like table. 0 if the input is no table or the table is empty.
get_table_size = function(value)
local count = 0
if type(value) == 'table' then
@@ -69,6 +114,10 @@ local utils = {
return count
end,
+ merge_tables = merge_tables,
+
+ clone_table = clone_table,
+
remove_from_array = function(array, element)
for index, value in pairs(array) do
if element == value then
@@ -77,58 +126,95 @@ local utils = {
end
end
end,
-}
---- https://stackoverflow.com/a/1283608/10193818
-local function merge_tables(target, t2)
- for k, v in pairs(t2) do
- if type(v) == 'table' then
- if type(target[k] or false) == 'table' then
- merge_tables(target[k] or {}, t2[k] or {})
- elseif target[k] == nil then
- target[k] = v
+ ---Scan for an optional argument.
+ ---
+ ---@param initial_delimiter? string # The character that marks the beginning of an optional argument (by default `[`).
+ ---@param end_delimiter? string # The character that marks the end of an optional argument (by default `]`).
+ ---
+ ---@return string|nil # The string that was enclosed by the delimiters. The delimiters themselves are not returned.
+ scan_oarg = function(initial_delimiter, end_delimiter)
+ if initial_delimiter == nil then
+ initial_delimiter = '['
+ end
+
+ if end_delimiter == nil then
+ end_delimiter = ']'
+ end
+
+ local function convert_token(t)
+ if t.index ~= nil then
+ return utf8.char(t.index)
+ else
+ return '\\' .. t.csname
end
- elseif target[k] == nil then
- target[k] = v
end
- end
- return target
-end
---- http://lua-users.org/wiki/CopyTable
-local function clone_table(orig)
- local orig_type = type(orig)
- local copy
- if orig_type == 'table' then
- copy = {}
- for orig_key, orig_value in next, orig, nil do
- copy[clone_table(orig_key)] = clone_table(orig_value)
+ local function get_next_char()
+ local t = token.get_next()
+ return convert_token(t), t
end
- setmetatable(copy, clone_table(getmetatable(orig)))
- else -- number, string, boolean, etc
- copy = orig
- end
- return copy
-end
---- This table stores all allowed option keys.
-local all_options = {
- convert_dimensions = false,
- debug = false,
- default = true,
- defaults = false,
- defs = false,
- format_keys = false,
- hooks = {},
- naked_as_value = false,
- no_error = false,
- postprocess = false,
- preprocess = false,
- unpack = true,
+ local char, t = get_next_char()
+ if char == initial_delimiter then
+ local oarg = {}
+ char = get_next_char()
+ while char ~= end_delimiter do
+ table.insert(oarg, char)
+ char = get_next_char()
+ end
+ return table.concat(oarg, '')
+ else
+ token.put_next(t)
+ end
+ end,
+}
+
+local namespace = {
+ opts = {
+ convert_dimensions = false,
+ debug = false,
+ default = true,
+ defaults = false,
+ defs = false,
+ format_keys = false,
+ hooks = {},
+ naked_as_value = false,
+ no_error = false,
+ unpack = true,
+ },
+
+ hooks = {
+ kv_string = true,
+ keys_before_opts = true,
+ result_before_opts = true,
+ keys_before_def = true,
+ result_before_def = true,
+ keys = true,
+ result = true,
+ },
+
+ attrs = {
+ alias = true,
+ always_present = true,
+ choices = true,
+ data_type = true,
+ default = true,
+ exclusive_group = true,
+ l3_tl_set = true,
+ macro = true,
+ match = true,
+ name = true,
+ opposite_keys = true,
+ pick = true,
+ process = true,
+ required = true,
+ sub_keys = true,
+ },
}
--- The default options.
-local default_options = clone_table(all_options)
+local default_options = clone_table(namespace.opts)
local function throw_error(message)
if type(tex.error) == 'function' then
@@ -144,16 +230,15 @@ local l3_code_cctab = 10
-- @section
--- The function `render(tbl)` reverses the function
--- `parse(kv_string)`. It takes a Lua table and converts this table
--- into a key-value string. The resulting string usually has a
--- different order as the input table. In Lua only tables with
--- 1-based consecutive integer keys (a.k.a. array tables) can be
--- parsed in order.
---
--- @tparam table result A table to be converted into a key-value string.
---
--- @treturn string A key-value string that can be passed to a TeX
--- macro.
+--- `parse(kv_string)`. It takes a Lua table and converts this table
+--- into a key-value string. The resulting string usually has a
+--- different order as the input table. In Lua only tables with
+--- 1-based consecutive integer keys (a.k.a. array tables) can be
+--- parsed in order.
+---
+---@param result table # A table to be converted into a key-value string.
+---
+---@return string # A key-value string that can be passed to a TeX macro.
local function render(result)
local function render_inner(result)
local output = {}
@@ -183,20 +268,19 @@ local function render(result)
end
--- The function `stringify(tbl, for_tex)` converts a Lua table into a
--- printable string. Stringify a table means to convert the table into
--- a string. This function is used to realize the `debug` function.
--- `stringify(tbl, true)` (`for_tex = true`) generates a string which
--- can be embeded into TeX documents. The macro `\luakeysdebug{}` uses
--- this option. `stringify(tbl, false)` or `stringify(tbl)` generate a
--- string suitable for the terminal.
---
--- @tparam table result A table to stringify.
---
--- @tparam boolean for_tex Stringify the table into a text string that
--- can be embeded inside a TeX document via tex.print(). Curly braces
--- and whites spaces are escaped.
---
--- https://stackoverflow.com/a/54593224/10193818
+--- printable string. Stringify a table means to convert the table into
+--- a string. This function is used to realize the `debug` function.
+--- `stringify(tbl, true)` (`for_tex = true`) generates a string which
+--- can be embeded into TeX documents. The macro `\luakeysdebug{}` uses
+--- this option. `stringify(tbl, false)` or `stringify(tbl)` generate a
+--- string suitable for the terminal.
+---
+---@see https://stackoverflow.com/a/54593224/10193818
+---
+---@param result table # A table to stringify.
+---@param for_tex? boolean # Stringify the table into a text string that can be embeded inside a TeX document via tex.print(). Curly braces and whites spaces are escaped.
+---
+---@return string
local function stringify(result, for_tex)
local line_break, start_bracket, end_bracket, indent
@@ -242,7 +326,8 @@ local function stringify(result, for_tex)
add(0, stringify_inner(value, depth + 1))
add(depth, end_bracket .. ',');
else
- add(depth, key .. ' = ' .. start_bracket .. end_bracket .. ',')
+ add(depth,
+ key .. ' = ' .. start_bracket .. end_bracket .. ',')
end
else
if (type(value) == 'string') then
@@ -259,19 +344,17 @@ local function stringify(result, for_tex)
return table.concat(output, line_break)
end
- return
- start_bracket .. line_break .. stringify_inner(result, 1) .. line_break ..
- end_bracket
+ return start_bracket .. line_break .. stringify_inner(result, 1) ..
+ line_break .. end_bracket
end
---- The function `debug(tbl)` pretty prints a Lua table to standard
+--- The function `debug(result)` pretty prints a Lua table to standard
-- output (stdout). It is a utility function that can be used to
-- debug and inspect the resulting Lua table of the function
-- `parse`. You have to compile your TeX document in a console to
-- see the terminal output.
--
--- @tparam table result A table to be printed to standard output for
--- debugging purposes.
+---@param result table # A table to be printed to standard output for debugging purposes.
local function debug(result)
print('\n' .. stringify(result, false))
end
@@ -280,19 +363,23 @@ end
-- @section
--- Generate the PEG parser using Lpeg.
---
--- Explanations of some LPeg notation forms:
---
--- * `patt ^ 0` = `expression *`
--- * `patt ^ 1` = `expression +`
--- * `patt ^ -1` = `expression ?`
--- * `patt1 * patt2` = `expression1 expression2`: Sequence
--- * `patt1 + patt2` = `expression1 / expression2`: Ordered choice
---
--- * [TUGboat article: Parsing complex data formats in LuaTEX with LPEG](https://tug.org/TUGboat/tb40-2/tb125menke-Patterndf)
---
--- @treturn userdata The parser.
-local function generate_parser(initial_rule, convert_dimensions)
+---
+--- Explanations of some LPeg notation forms:
+---
+--- * `patt ^ 0` = `expression *`
+--- * `patt ^ 1` = `expression +`
+--- * `patt ^ -1` = `expression ?`
+--- * `patt1 * patt2` = `expression1 expression2`: Sequence
+--- * `patt1 + patt2` = `expression1 / expression2`: Ordered choice
+---
+--- * [TUGboat article: Parsing complex data formats in LuaTEX with LPEG](https://tug.or-g/TUGboat/tb40-2/tb125menke-Patterndf)
+---
+---@param initial_rule string # The name of the first rule of the grammar table passed to the `lpeg.P(attern)` function (e. g. `list`, `number`).
+---@param convert_dimensions? boolean # Whether the dimensions should be converted to scaled points (by default `false`).
+---
+---@return userdata # The parser.
+local function generate_parser(initial_rule,
+ convert_dimensions)
if convert_dimensions == nil then
convert_dimensions = false
end
@@ -315,7 +402,17 @@ local function generate_parser(initial_rule, convert_dimensions)
return white_space ^ 0 * Pattern(match) * white_space ^ 0
end
+ --- Convert a dimension to an normalized dimension string or an
+ --- integer in the scaled points format.
+ ---
+ ---@param input string
+ ---
+ ---@return integer|string # A dimension as an integer or a dimension string.
local capture_dimension = function(input)
+ -- Remove all whitespaces
+ input = input:gsub('%s+', '')
+ -- Convert the unit string into lowercase.
+ input = input:lower()
if convert_dimensions then
return tex.sp(input)
else
@@ -325,27 +422,27 @@ local function generate_parser(initial_rule, convert_dimensions)
--- Add values to a table in two modes:
--
- -- # Key value pair
+ -- Key-value pair:
--
- -- If arg1 and arg2 are not nil, then arg1 is the key and arg2 is the
+ -- If `arg1` and `arg2` are not nil, then `arg1` is the key and `arg2` is the
-- value of a new table entry.
--
- -- # Index value
+ -- Indexed value:
--
- -- If arg2 is nil, then arg1 is the value and is added as an indexed
+ -- If `arg2` is nil, then `arg1` is the value and is added as an indexed
-- (by an integer) value.
--
- -- @tparam table table
- -- @tparam mixed arg1
- -- @tparam mixed arg2
- --
- -- @treturn table
- local add_to_table = function(table, arg1, arg2)
+ ---@param result table # The result table to which an additional key-value pair or value should to be added
+ ---@param arg1 any # The key or the value.
+ ---@param arg2? any # Always the value.
+ ---
+ ---@return table # The result table to which an additional key-value pair or value has been added.
+ local add_to_table = function(result, arg1, arg2)
if arg2 == nil then
- local index = #table + 1
- return rawset(table, index, arg1)
+ local index = #result + 1
+ return rawset(result, index, arg1)
else
- return rawset(table, arg1, arg2)
+ return rawset(result, arg1, arg2)
end
end
@@ -438,6 +535,7 @@ local function generate_parser(initial_rule, convert_dimensions)
-- 'bp' / 'BP' / 'cc' / etc.
-- https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua
+ -- https://github.com/TeX-Live/luatex/blob/51db1985f5500dafd2393aa2e403fefa57d3cb76/source/texk/web2c/luatexdir/lua/ltexlib.c#L434-L625
unit =
Pattern('bp') + Pattern('BP') +
Pattern('cc') + Pattern('CC') +
@@ -447,10 +545,12 @@ local function generate_parser(initial_rule, convert_dimensions)
Pattern('ex') + Pattern('EX') +
Pattern('in') + Pattern('IN') +
Pattern('mm') + Pattern('MM') +
+ Pattern('mu') + Pattern('MU') +
Pattern('nc') + Pattern('NC') +
Pattern('nd') + Pattern('ND') +
Pattern('pc') + Pattern('PC') +
Pattern('pt') + Pattern('PT') +
+ Pattern('px') + Pattern('PX') +
Pattern('sp') + Pattern('SP'),
-- '"' ('\"' / !'"')* '"'
@@ -483,7 +583,8 @@ local function visit_tree(tree, callback_func)
callback_func)
for key, value in pairs(current) do
if type(value) == 'table' then
- value = visit_tree_recursive(tree, value, {}, depth + 1, callback_func)
+ value = visit_tree_recursive(tree, value, {}, depth + 1,
+ callback_func)
end
key, value = callback_func(key, value, depth, current, tree)
@@ -514,7 +615,7 @@ local is = {
return true
end
local parser = generate_parser('boolean_only', false)
- local result = parser:match(value)
+ local result = parser:match(tostring(value))
return result ~= nil
end,
@@ -523,7 +624,7 @@ local is = {
return false
end
local parser = generate_parser('dimension_only', false)
- local result = parser:match(value)
+ local result = parser:match(tostring(value))
return result ~= nil
end,
@@ -543,7 +644,7 @@ local is = {
return true
end
local parser = generate_parser('number_only', false)
- local result = parser:match(value)
+ local result = parser:match(tostring(value))
return result ~= nil
end,
@@ -555,14 +656,13 @@ local is = {
--- Apply the key-value-pair definitions (defs) on an input table in a
--- recursive fashion.
---
----@param defs table A table containing all definitions.
----@param opts table The parse options table.
----@param input table The current input table.
----@param output table The current output table.
----@param unknown table Always the root unknown table.
----@param key_path table An array of key names leading to the current
----@param input_root table The root input table
---- input and output table.
+---@param defs table # A table containing all definitions.
+---@param opts table # The parse options table.
+---@param input table # The current input table.
+---@param output table # The current output table.
+---@param unknown table # Always the root unknown table.
+---@param key_path table # An array of key names leading to the current
+---@param input_root table # The root input table input and output table.
local function apply_definitions(defs,
opts,
input,
@@ -583,7 +683,7 @@ local function apply_definitions(defs,
return new_key_path
end
- local function set_default_value(def)
+ local function get_default_value(def)
if def.default ~= nil then
return def.default
elseif opts ~= nil and opts.default ~= nil then
@@ -599,7 +699,7 @@ local function apply_definitions(defs,
return value
-- naked keys: values with integer keys
elseif utils.remove_from_array(input, search_key) ~= nil then
- return set_default_value(def)
+ return get_default_value(def)
end
end
@@ -634,7 +734,7 @@ local function apply_definitions(defs,
always_present = function(value, key, def)
if value == nil and def.always_present then
- return set_default_value(def)
+ return get_default_value(def)
end
end,
@@ -692,9 +792,10 @@ local function apply_definitions(defs,
throw_error('Unknown data type: ' .. def.data_type)
end
if converted == nil then
- throw_error('The value “' .. value .. '” of the key “' .. key ..
- '” could not be converted into the data type “' ..
- def.data_type .. '”!')
+ throw_error(
+ 'The value “' .. value .. '” of the key “' .. key ..
+ '” could not be converted into the data type “' ..
+ def.data_type .. '”!')
else
return converted
end
@@ -723,7 +824,8 @@ local function apply_definitions(defs,
return
end
if def.l3_tl_set ~= nil then
- tex.print(l3_code_cctab, '\\tl_set:Nn \\g_' .. def.l3_tl_set .. '_tl')
+ tex.print(l3_code_cctab,
+ '\\tl_set:Nn \\g_' .. def.l3_tl_set .. '_tl')
tex.print('{' .. value .. '}')
end
end,
@@ -747,8 +849,9 @@ local function apply_definitions(defs,
end
local match = string.match(value, def.match)
if match == nil then
- throw_error('The value “' .. value .. '” of the key “' .. key ..
- '” does not match “' .. def.match .. '”!')
+ throw_error(
+ 'The value “' .. value .. '” of the key “' .. key ..
+ '” does not match “' .. def.match .. '”!')
else
return match
end
@@ -780,6 +883,41 @@ local function apply_definitions(defs,
end
end,
+ pick = function(value, key, def)
+ if def.pick then
+ if type(def.pick) == 'string' and is[def.pick] == nil then
+ throw_error(
+ 'Wrong setting. Allowed settings for the attribute “def.pick” are: true, boolean, dimension, integer, number, string. Got “' ..
+ tostring(def.pick) .. '”.')
+ end
+
+ if value ~= nil then
+ return value
+ end
+ for i, v in pairs(input) do
+ -- We can not use ipairs here. `ipairs(t)` iterates up to the
+ -- first absent index. Values are deleted from the `input`
+ -- table.
+ if type(i) == 'number' then
+ local picked_value = nil
+ -- Pick a value by type: boolean, dimension, integer, number, string
+ if is[def.pick] ~= nil then
+ if is[def.pick](v) then
+ picked_value = v
+ end
+ -- Pick every value
+ elseif v ~= nil then
+ picked_value = v
+ end
+ if picked_value ~= nil then
+ input[i] = nil
+ return picked_value
+ end
+ end
+ end
+ end
+ end,
+
required = function(value, key, def)
if def.required ~= nil and def.required and value == nil then
throw_error(string.format('Missing required key “%s”!', key))
@@ -797,8 +935,8 @@ local function apply_definitions(defs,
elseif type(value) == 'table' then
v = value
end
- v = apply_definitions(def.sub_keys, opts, v, output[key], unknown,
- add_to_key_path(key_path, key), input_root)
+ v = apply_definitions(def.sub_keys, opts, v, output[key],
+ unknown, add_to_key_path(key_path, key), input_root)
if utils.get_table_size(v) > 0 then
return v
end
@@ -821,23 +959,33 @@ local function apply_definitions(defs,
end
for index, def in pairs(defs) do
- --- Find key and def
+ -- Find key and def
local key
- if type(def) == 'table' and def.name == nil and type(index) == 'string' then
+ -- `{ key1 = { }, key2 = { } }`
+ if type(def) == 'table' and def.name == nil and type(index) ==
+ 'string' then
key = index
+ -- `{ { name = 'key1' }, { name = 'key2' } }`
elseif type(def) == 'table' and def.name ~= nil then
key = def.name
+ -- Definitions as strings in an array: `{ 'key1', 'key2' }`
elseif type(index) == 'number' and type(def) == 'string' then
key = def
- def = { default = true }
+ def = { default = get_default_value({}) }
end
if type(def) ~= 'table' then
- throw_error('Key definition must be a table')
+ throw_error('Key definition must be a table!')
+ end
+
+ for attr, _ in pairs(def) do
+ if namespace.attrs[attr] == nil then
+ throw_error('Unknown definition attribute: ' .. tostring(attr))
+ end
end
if key == nil then
- throw_error('key name couldn’t be detected!')
+ throw_error('Key name couldn’t be detected!')
end
local value = find_value(key, def)
@@ -845,6 +993,7 @@ local function apply_definitions(defs,
for _, def_opt in ipairs({
'alias',
'opposite_keys',
+ 'pick',
'always_present',
'required',
'data_type',
@@ -888,14 +1037,14 @@ end
--- Parse a LaTeX/TeX style key-value string into a Lua table.
---
----@param kv_string string A string in the TeX/LaTeX style key-value format as described above.
----@param opts table A table containing the settings:
+---@param kv_string string # A string in the TeX/LaTeX style key-value format as described above.
+---@param opts table # A table containing the settings:
--- `convert_dimensions`, `unpack`, `naked_as_value`, `converter`,
--- `debug`, `preprocess`, `postprocess`.
--
----@return table result The final result of all individual parsing and normalization steps.
----@return table unknown A table with unknown, undefinied key-value pairs.
----@return table raw The unprocessed, raw result of the LPeg parser.
+---@return table result # The final result of all individual parsing and normalization steps.
+---@return table unknown # A table with unknown, undefinied key-value pairs.
+---@return table raw # The unprocessed, raw result of the LPeg parser.
local function parse(kv_string, opts)
if kv_string == nil then
return {}
@@ -903,21 +1052,21 @@ local function parse(kv_string, opts)
--- Normalize the parse options.
---
- --- @param opts table Options in a raw format. The table may be empty or some keys are not set.
+ ---@param opts table # Options in a raw format. The table may be empty or some keys are not set.
---
- --- @return table
+ ---@return table
local function normalize_opts(opts)
if type(opts) ~= 'table' then
opts = {}
end
for key, _ in pairs(opts) do
- if all_options[key] == nil then
+ if namespace.opts[key] == nil then
throw_error('Unknown parse option: ' .. tostring(key) .. '!')
end
end
local old_opts = opts
opts = {}
- for name, _ in pairs(all_options) do
+ for name, _ in pairs(namespace.opts) do
if old_opts[name] ~= nil then
opts[name] = old_opts[name]
else
@@ -925,18 +1074,8 @@ local function parse(kv_string, opts)
end
end
- local hooks = {
- kv_string = true,
- keys_before_opts = true,
- result_before_opts = true,
- keys_before_def = true,
- result_before_def = true,
- keys = true,
- result = true,
- }
-
for hook in pairs(opts.hooks) do
- if hooks[hook] == nil then
+ if namespace.hooks[hook] == nil then
throw_error('Unknown hook: ' .. tostring(hook) .. '!')
end
end
@@ -983,8 +1122,8 @@ local function parse(kv_string, opts)
-- tasks are performed on the raw input table coming directly from
-- the PEG parser:
--
- --- @param result table The raw input table coming directly from the PEG parser
- --- @param opts table Some options.
+ ---@param result table # The raw input table coming directly from the PEG parser
+ ---@param opts table # Some options.
local function apply_opts(result, opts)
local callbacks = {
unpack = function(key, value)
@@ -1012,7 +1151,8 @@ local function parse(kv_string, opts)
elseif style == 'upper' then
key = key:upper()
else
- throw_error('Unknown style to format keys: ' .. tostring(style) ..
+ throw_error('Unknown style to format keys: ' ..
+ tostring(style) ..
' Allowed styles are: lower, snake, upper')
end
end
@@ -1031,8 +1171,9 @@ local function parse(kv_string, opts)
if opts.format_keys then
if type(opts.format_keys) ~= 'table' then
- throw_error('The option “format_keys” has to be a table not ' ..
- type(opts.format_keys))
+ throw_error(
+ 'The option “format_keys” has to be a table not ' ..
+ type(opts.format_keys))
end
result = visit_tree(result, callbacks.format_key)
end
@@ -1045,8 +1186,8 @@ local function parse(kv_string, opts)
local unknown = nil
if type(opts.defs) == 'table' then
apply_hooks('before_defs')
- result, unknown = apply_definitions(opts.defs, opts, result, {}, {}, {},
- clone_table(result))
+ result, unknown = apply_definitions(opts.defs, opts, result, {}, {},
+ {}, clone_table(result))
end
apply_hooks()
@@ -1077,6 +1218,26 @@ local result_store = {}
-- @section
local export = {
+ version = { 0, 7, 0 },
+
+ namespace = namespace,
+
+ ---This function is used in the documentation.
+ ---
+ ---@param from string # A key in the namespace table, either `opts`, `hook` or `attrs`.
+ print_names = function(from)
+ local names = {}
+ for name in pairs(namespace[from]) do
+ table.insert(names, name)
+ end
+ table.sort(names)
+ tex.print(table.concat(names, ', '))
+ end,
+
+ print_default = function(from, name)
+ tex.print(tostring(namespace[from][name]))
+ end,
+
--- @see default_options
opts = default_options,
@@ -1089,7 +1250,10 @@ local export = {
define = function(defs, opts)
return function(kv_string, inner_opts)
local options
- if inner_opts ~= nil then
+
+ if inner_opts ~= nil and opts ~= nil then
+ options = merge_tables(opts, inner_opts)
+ elseif inner_opts ~= nil then
options = inner_opts
elseif opts ~= nil then
options = opts
@@ -1116,11 +1280,9 @@ local export = {
-- Therefore, it is not necessary to pollute the global namespace to
-- store results for the later usage.
--
- -- @tparam string identifier The identifier under which the result is
- -- saved.
+ ---@param identifier string # The identifier under which the result is saved.
--
- -- @tparam table result A result to be stored and that was created by
- -- the key-value parser.
+ ---@param result table # A result to be stored and that was created by the key-value parser.
save = function(identifier, result)
result_store[identifier] = result
end,
@@ -1128,8 +1290,9 @@ local export = {
--- The function `get(identifier): table` retrieves a saved result
-- from the result store.
--
- -- @tparam string identifier The identifier under which the result was
- -- saved.
+ ---@param identifier string # The identifier under which the result was saved.
+ ---
+ ---@return table
get = function(identifier)
-- if result_store[identifier] == nil then
-- throw_error('No stored result was found for the identifier \'' .. identifier .. '\'')
@@ -1138,6 +1301,8 @@ local export = {
end,
is = is,
+
+ utils = utils,
}
return export
diff --git a/macros/luatex/generic/luakeys/luakeys.sty b/macros/luatex/generic/luakeys/luakeys.sty
index 51e2c9bec5..d0917f1d9d 100644
--- a/macros/luatex/generic/luakeys/luakeys.sty
+++ b/macros/luatex/generic/luakeys/luakeys.sty
@@ -17,5 +17,5 @@
% luakeys-debug.sty and luakeys-debug.tex.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{luakeys}[2022/06/09 v0.6 Parsing key-value options using Lua.]
+\ProvidesPackage{luakeys}[2022/07/06 0.7.0 Parsing key-value options using Lua.]
\directlua{luakeys = require('luakeys')}