summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-12-29 03:00:50 +0000
committerNorbert Preining <norbert@preining.info>2020-12-29 03:00:50 +0000
commitec483f80cce5e50f1ea09f9cdea99d26fbba5c5d (patch)
tree69bf255fb4232c3d9113c03f460cf21b3a74df91 /macros
parent07b20138841bb0e4c45e74a2a1d06cc91fe5a861 (diff)
CTAN sync 202012290300
Diffstat (limited to 'macros')
-rw-r--r--macros/generic/expkv-def/README.md2
-rw-r--r--macros/generic/expkv-def/expkv-def.dtx90
-rw-r--r--macros/generic/expkv-def/expkv-def.pdfbin356349 -> 379054 bytes
-rw-r--r--macros/generic/expkv/README.md2
-rw-r--r--macros/generic/expkv/expkv.dtx235
-rw-r--r--macros/generic/expkv/expkv.pdfbin410888 -> 411252 bytes
-rw-r--r--macros/latex/contrib/froufrou/LICENSE11
-rw-r--r--macros/latex/contrib/froufrou/README.md13
-rw-r--r--macros/latex/contrib/froufrou/froufrou.dtx316
-rw-r--r--macros/latex/contrib/froufrou/froufrou.ins50
-rw-r--r--macros/latex/contrib/froufrou/froufrou.pdfbin0 -> 40776 bytes
11 files changed, 546 insertions, 173 deletions
diff --git a/macros/generic/expkv-def/README.md b/macros/generic/expkv-def/README.md
index b2172d3ab1..ffea8dd5ca 100644
--- a/macros/generic/expkv-def/README.md
+++ b/macros/generic/expkv-def/README.md
@@ -1,7 +1,7 @@
-------------------------------------------------------------------------------
# expkv-def -- a key-defining frontend for expkv
-Version 2020-10-12 v0.6
+Version 2020-12-28 v0.7
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
diff --git a/macros/generic/expkv-def/expkv-def.dtx b/macros/generic/expkv-def/expkv-def.dtx
index 2dc4164153..5edf48780c 100644
--- a/macros/generic/expkv-def/expkv-def.dtx
+++ b/macros/generic/expkv-def/expkv-def.dtx
@@ -171,6 +171,7 @@ and the derived files expkv-def.pdf
\DoNotIndex{\@,\unexpanded,\string,\expanded,\dimexpr,\global,\glueexpr,\hbox}
\DoNotIndex{\numexpr,\RequirePackage,\setbox,\the,\unless,\xdef,\@firstofone}
\DoNotIndex{\@firstoftwo,\@gobble,\@secondoftwo,\meaning,\detokenize}
+\DoNotIndex{\romannumeral,\^}
\DoNotIndex{\ifcsname}
\DoNotIndex{\ifx}
\DoNotIndex{\ifdefined}
@@ -362,7 +363,7 @@ and the derived files expkv-def.pdf
% |\edef|.
% \end{function}
%
-% \begin{function}{default,qdefault,edefault}
+% \begin{function}{default,qdefault,odefault,fdefault,edefault}
% \begin{syntax}
% default \key\ = \marg{definition} \prefixes3223
% \end{syntax}
@@ -370,11 +371,18 @@ and the derived files expkv-def.pdf
% \key\ can be of any argument-grabbing kind, and when used without a \val\
% it will be passed \meta{definition} instead. The |qdefault| variant will
% expand the \key's code once, so will be slightly quicker, but not change if
-% you redefine \key. The |edefault| on the other hand fully expands the
-% \key-code with \meta{definition} as its argument inside of an |\edef|.
+% you redefine \key. |odefault| is just another name for |qdefault|. The
+% |fdefault| version will expand the key code until a non-expandable token or
+% a space is found, a space would be gobbled.\footnotemark{} The |edefault| on the other hand fully expands
+% the \key-code with \meta{definition} as its argument inside of an |\edef|.
% \end{function}
+% \footnotetext
+% {^^A
+% For those familiar with \TeX-coding: This uses a
+% \cs[no-index]{romannumeral}-expansion.
+% }
%
-% \begin{function}{initial,oinitial,einitial}
+% \begin{function}{initial,oinitial,finitial,einitial}
% \begin{syntax}
% initial \key\ = \{\val\} \prefixes3333
% \end{syntax}
@@ -382,8 +390,11 @@ and the derived files expkv-def.pdf
% taking \key. It'll just call the key-macro of \key\ and pass it \val. The
% |einitial| variant will expand \val\ using an |\edef| expansion prior to
% passing it to the key-macro and the |oinitial| variant will expand the first
-% token in \val\ once.
+% token in \val\ once. |finitial| will expand \val\ until a non-expandable
+% token or a space is found, a space would be
+% gobbled.\footnotemark
% \end{function}
+% \footnotetext{Again using \cs[no-index]{romannumeral}.}
%
% \begin{function}{bool,gbool,boolTF,gboolTF}
% \begin{syntax}
@@ -755,8 +766,8 @@ and the derived files expkv-def.pdf
% \begin{macro}{\ekvdVersion,\ekvdDate}
% We're on our first input, so lets store the version and date in a macro.
% \begin{macrocode}
-\def\ekvdVersion{0.6}
-\def\ekvdDate{2020-10-12}
+\def\ekvdVersion{0.7}
+\def\ekvdDate{2020-12-28}
% \end{macrocode}
% \end{macro}
%
@@ -904,15 +915,11 @@ and the derived files expkv-def.pdf
{%
\ekvd@ifalso
{%
- \ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekvd@add@noval{#1}}}%
+ \ekv@expargtwice{\ekvd@add@noval{#1}}%
{\ekvchangeset{#2}}%
\ekvd@assert@not@protected@also
}%
- {%
- \ekv@expB@unbraceA
- {\ekv@expB@unbraceA{\ekvdefNoVal\ekvd@set{#1}}}%
- {\ekvchangeset{#2}}%
- }%
+ {\ekv@expargtwice{\ekvdefNoVal\ekvd@set{#1}}{\ekvchangeset{#2}}}%
}%
}%
}
@@ -942,7 +949,7 @@ and the derived files expkv-def.pdf
\ekvd@assert@not@long
\ekvd@prot#1\ekvd@tmp{#3}%
\ekvd@ifalso
- {\ekv@expB@unbraceA{\ekvd@add@noval{#2}}\ekvd@tmp{}}%
+ {\ekv@exparg{\ekvd@add@noval{#2}}\ekvd@tmp{}}%
{\ekvletNoVal\ekvd@set{#2}\ekvd@tmp}%
}%
}%
@@ -964,7 +971,7 @@ and the derived files expkv-def.pdf
{%
\ekvd@prot\ekvd@long#1\ekvd@tmp##1{#3}%
\ekvd@ifalso
- {\ekv@expB@unbraceA{\ekvd@add@val{#2}}{\ekvd@tmp{##1}}{}}%
+ {\ekv@exparg{\ekvd@add@val{#2}}{\ekvd@tmp{##1}}{}}%
{\ekvlet\ekvd@set{#2}\ekvd@tmp}%
}%
}%
@@ -974,35 +981,41 @@ and the derived files expkv-def.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekvd@type@default,\ekvd@t@default,\ekvd@t@qdefault}
+% \begin{macro}[internal]
+% {
+% \ekvd@type@default,\ekvd@t@default,\ekvd@t@qdefault,\ekvd@t@odefault,
+% \ekvd@t@fdefault
+% }
% |\ekvd@type@default| asserts there was an argument, also the key for which one
% wants to set a default has to be already defined (this is not so important for
% |default|, but |qdefault| requires is). If everything is good, |\edef| a
% temporary macro that expands |\ekvd@set| and the |\csname| for the key, and in
% the case of |qdefault| does the first expansion step of the key-macro.
% \begin{macrocode}
-\protected\long\def\ekvd@type@default#1#2#3%
+\protected\long\def\ekvd@type@default#1#2#3#4%
{%
\ekvd@assert@arg
{%
- \ekvifdefined\ekvd@set{#2}%
+ \ekvifdefined\ekvd@set{#3}%
{%
\ekvd@assert@not@new
\ekvd@assert@not@long
\ekvd@prot\edef\ekvd@tmp
{%
\unexpanded\expandafter#1%
- {\csname\ekv@name\ekvd@set{#2}\endcsname{#3}}%
+ {#2\csname\ekv@name\ekvd@set{#3}\endcsname{#4}}%
}%
\ekvd@ifalso
- {\ekv@expB@unbraceA{\ekvd@add@noval{#2}}\ekvd@tmp{}}%
- {\ekvletNoVal\ekvd@set{#2}\ekvd@tmp}%
+ {\ekv@exparg{\ekvd@add@noval{#3}}\ekvd@tmp{}}%
+ {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}%
}%
- {\ekvd@err@undefined@key{#2}}%
+ {\ekvd@err@undefined@key{#3}}%
}%
}
-\protected\def\ekvd@t@default{\ekvd@type@default{}}
-\protected\def\ekvd@t@qdefault{\ekvd@type@default{\expandafter\expandafter}}
+\protected\def\ekvd@t@default{\ekvd@type@default{}{}}
+\protected\def\ekvd@t@qdefault{\ekvd@type@default{\expandafter\expandafter}{}}
+\let\ekvd@t@odefault\ekvd@t@qdefault
+\protected\def\ekvd@t@fdefault{\ekvd@type@default{}{\romannumeral`\^^@}}
% \end{macrocode}
% \end{macro}
%
@@ -1021,7 +1034,7 @@ and the derived files expkv-def.pdf
\ekvd@prot\edef\ekvd@tmp
{\csname\ekv@name\ekvd@set{#1}\endcsname{#2}}%
\ekvd@ifalso
- {\ekv@expB@unbraceA{\ekvd@add@noval{#1}}\ekvd@tmp{}}%
+ {\ekv@exparg{\ekvd@add@noval{#1}}\ekvd@tmp{}}%
{\ekvletNoVal\ekvd@set{#1}\ekvd@tmp}%
}%
{\ekvd@err@undefined@key{#1}}%
@@ -1030,28 +1043,31 @@ and the derived files expkv-def.pdf
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekvd@t@initial,\ekvd@t@oinitial,\ekvd@t@einitial}
+% \begin{macro}[internal]
+% {\ekvd@t@initial,\ekvd@t@oinitial,\ekvd@t@finitial,\ekvd@t@einitial}
% \begin{macrocode}
-\long\def\ekvd@type@initial#1#2#3%
+\long\def\ekvd@type@initial#1#2#3#4%
{%
\ekvd@assert@arg
{%
- \ekvifdefined\ekvd@set{#2}%
+ \ekvifdefined\ekvd@set{#3}%
{%
\ekvd@assert@not@new
\ekvd@assert@not@also
\ekvd@assert@not@long
\ekvd@assert@not@protected
- #1{#3}%
- \csname\ekv@name\ekvd@set{#2}\expandafter\endcsname\expandafter
+ #1{#2#4}%
+ \csname\ekv@name\ekvd@set{#3}\expandafter\endcsname\expandafter
{\ekvd@tmp}%
}%
- {\ekvd@err@undefined@key{#2}}%
+ {\ekvd@err@undefined@key{#3}}%
}%
}
-\def\ekvd@t@initial{\ekvd@type@initial{\def\ekvd@tmp}}
-\def\ekvd@t@oinitial{\ekvd@type@initial{\ekv@expB@unbraceA{\def\ekvd@tmp}}}
-\def\ekvd@t@einitial{\ekvd@type@initial{\edef\ekvd@tmp}}
+\def\ekvd@t@initial{\ekvd@type@initial{\def\ekvd@tmp}{}}
+\def\ekvd@t@oinitial{\ekvd@type@initial{\ekv@exparg{\def\ekvd@tmp}}{}}
+\def\ekvd@t@einitial{\ekvd@type@initial{\edef\ekvd@tmp}{}}
+\def\ekvd@t@finitial
+ {\ekvd@type@initial{\ekv@exparg{\def\ekvd@tmp}}{\romannumeral`\^^@}}
% \end{macrocode}
% \end{macro}
%
@@ -1346,7 +1362,7 @@ and the derived files expkv-def.pdf
\edef\ekvd@tmp{\ekvd@set}%
\expandafter\ekvd@type@meta@a\expandafter{\ekvd@tmp}{#7}{#2}%
\ekvd@ifalso
- {\ekv@expB@unbraceA{#3{#6}}{\ekvd@tmp#4}{#5}}%
+ {\ekv@exparg{#3{#6}}{\ekvd@tmp#4}{#5}}%
{\csname ekvlet#1\endcsname\ekvd@set{#6}\ekvd@tmp}%
}%
}%
@@ -1386,7 +1402,7 @@ and the derived files expkv-def.pdf
{%
\ekvd@type@meta@a#7{#2}%
\ekvd@ifalso
- {\ekv@expB@unbraceA{#3{#6}}{\ekvd@tmp#4}{#5}}%
+ {\ekv@exparg{#3{#6}}{\ekvd@tmp#4}{#5}}%
{\csname ekvlet#1\endcsname\ekvd@set{#6}\ekvd@tmp}%
}%
}%
@@ -1424,7 +1440,7 @@ and the derived files expkv-def.pdf
{%
\ekvd@if@not@already@choice{#1}%
{%
- \ekv@expB@unbraceA
+ \ekv@exparg
{%
\expandafter\ekvd@add@aux
\csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}{#1}%
diff --git a/macros/generic/expkv-def/expkv-def.pdf b/macros/generic/expkv-def/expkv-def.pdf
index 73ddc853c6..727d6c43d4 100644
--- a/macros/generic/expkv-def/expkv-def.pdf
+++ b/macros/generic/expkv-def/expkv-def.pdf
Binary files differ
diff --git a/macros/generic/expkv/README.md b/macros/generic/expkv/README.md
index 730b302b5a..beeba1ca09 100644
--- a/macros/generic/expkv/README.md
+++ b/macros/generic/expkv/README.md
@@ -1,7 +1,7 @@
-------------------------------------------------------------------------------
# expkv -- an expandable key=val implementation
-Version 2020-10-10 v1.5
+Version 2020-12-28 v1.6
Released under the LaTeX Project Public License v1.3c or later
See http://www.latex-project.org/lppl.txt
diff --git a/macros/generic/expkv/expkv.dtx b/macros/generic/expkv/expkv.dtx
index 3cd8479be5..d3fc414f39 100644
--- a/macros/generic/expkv/expkv.dtx
+++ b/macros/generic/expkv/expkv.dtx
@@ -423,29 +423,40 @@ and the derived files expkv.pdf
%
% \begin{function}{\ekvparse}
% \begin{syntax}
-% \cs{ekvparse}\meta{cs1}\meta{cs2}\{\kv,\ldots\}
+% \cs{ekvparse}\marg{code1}\marg{code2}\{\kv,\ldots\}
% \end{syntax}
% This macro parses the \kv\ pairs and provides those list elements which are
-% only keys as the argument to \meta{cs1}, and those which are a \kv\ pair to
-% \meta{cs2} as two arguments. It is fully expandable as well and returns the
-% parsed list in |\unexpanded|, which has no effect outside of an |\expanded|
-% or |\edef| context\footnotemark.
+% only keys as an argument to \meta{code1}, and those which are a \kv\ pair
+% to \meta{code2} as two arguments. It is fully expandable as well and returns
+% each element of the parsed list in |\unexpanded|, which has no effect
+% outside of an |\expanded| or |\edef| context\footnotemark.
% If you need control over the necessary steps of expansion you
-% can use |\expanded| around it.
+% can use |\expanded| around it. You can use multiple tokens in \meta{code1}
+% and \meta{code2} or just a single control sequence name. In both cases the
+% found \key\ and \val\ are provided as a brace group following them.
%
% |\ekvbreak|, |\ekvsneak|, and |\ekvchangeset| and their relatives don't work
% in |\ekvparse|. It is analogue to \pkg{expl3}'s |\keyval_parse:NNn|, but
% not with the same parsing rules -- |\keyval_parse:NNn| throws an error on
% multiple equal signs per \kv\ pair and on empty \key\ names in a \kv\ pair,
% both of which |\ekvparse| doesn't deal with.
+% \end{function}
+% \footnotetext
+% {^^A
+% This is a change in behaviour, previously (v0.3 and before) \cs{ekvparse}
+% would expand in exactly two steps. This isn't always necessary, but makes
+% the parsing considerably slower. If this is necessary for your application
+% you can put an \cs[no-index]{expanded} around it and will still be faster
+% since you need only a single \cs[no-index]{expandafter} this way.^^A
+% }
%
% As a small example:
% \begin{lstlisting}
-% \ekvparse\handlekey\handlekeyval{foo = bar, key, baz={zzz}}
+% \ekvparse{\handlekey{S}}{\handlekeyval{S}}{foo = bar, key, baz={zzz}}
% \end{lstlisting}
-% would expand to
+% would be equivalent to
% \begin{lstlisting}
-% \handlekeyval{foo}{bar}\handlekey{key}\handlekeyval{baz}{zzz}
+% \handlekeyval{S}{foo}{bar}\handlekey{S}{key}\handlekeyval{S}{baz}{zzz}
% \end{lstlisting}
% and afterwards |\handlekey| and |\handlekeyval| would have to further handle
% the \key. There are no macros like these two contained in \expkv, you have
@@ -460,15 +471,6 @@ and the derived files expkv.pdf
% \begin{lstlisting}
% \handle\kv{foo}{bar}\k{key}\kv{baz}{zzz}
% \end{lstlisting}
-% \end{function}
-% \footnotetext
-% {^^A
-% This is a change in behaviour, previously (v0.3 and before) \cs{ekvparse}
-% would expand in exactly two steps. This isn't always necessary, but makes
-% the parsing considerably slower. If this is necessary for your application
-% you can put an \cs[no-index]{expanded} around it and will still be faster
-% since you need only a single \cs[no-index]{expandafter} this way.^^A
-% }.
%
% \subsection{Miscellaneous}
%
@@ -1082,8 +1084,8 @@ and the derived files expkv.pdf
% \begin{macro}{\ekvVersion,\ekvDate}
% We're on our first input, so lets store the version and date in a macro.
% \begin{macrocode}
-\def\ekvVersion{1.5}
-\def\ekvDate{2020-10-10}
+\def\ekvVersion{1.6}
+\def\ekvDate{2020-12-28}
% \end{macrocode}
% \end{macro}
%
@@ -1262,25 +1264,30 @@ and the derived files expkv.pdf
##1\ekv@nil
\ekv@mark#1%
#1\ekv@nil
- \ekv@stop
}%
\long\def\ekv@strip@a##1\ekv@mark#1{\ekv@strip@b##1\ekv@mark}%
- \long\def\ekv@strip@b##1#1\ekv@nil {\ekv@strip@c##1\ekv@nil}%
}
\ekv@strip{ }
-\long\def\ekv@strip@c\ekv@mark#1\ekv@nil\ekv@mark#2\ekv@nil\ekv@stop#3{#3{#1}}
+\long\def\ekv@strip@b#1 \ekv@nil{\ekv@strip@c#1\ekv@nil}
+\long\def\ekv@strip@c\ekv@mark#1\ekv@nil\ekv@mark#2\ekv@nil#3{#3{#1}}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[internal]{\ekv@expB@unbraceA,\ekv@expB@unbraceA@}
-% To reduce some code doublets while gaining some speed, it is often useful to
-% expand the first token in a definition once. Let's define a wrapper for this.
+% \begin{macro}[internal]
+% {\ekv@exparg,\ekv@exparg@,\ekv@expargtwice,\ekv@expargtwice@,\ekv@zero}
+% To reduce some code doublets while gaining some speed (and also as convenience
+% for other packages in the family), it is often useful to expand the first
+% token in a definition once. Let's define a wrapper for this.
+%
+% Also, to end a |\romannumeral| expansion, we want to use |\z@|, which is
+% contained in both plain \TeX\ and \LaTeX, but we use a private name for it to
+% make it easier to spot and hence easier to manage.
% \begin{macrocode}
-\long\def\ekv@expB@unbraceA#1#2%
- {%
- \expandafter\ekv@expB@unbraceA@\expandafter{#2}{#1}%
- }
-\long\def\ekv@expB@unbraceA@#1#2{#2{#1}}%
+\let\ekv@zero\z@
+\long\def\ekv@exparg#1#2{\expandafter\ekv@exparg@\expandafter{#2}{#1}}
+\long\def\ekv@exparg@#1#2{#2{#1}}%
+\long\def\ekv@expargtwice#1#2{\expandafter\ekv@expargtwice@\expandafter{#2}{#1}}
+\def\ekv@expargtwice@{\expandafter\ekv@exparg@\expandafter}
% \end{macrocode}
% \end{macro}
%
@@ -1294,7 +1301,7 @@ and the derived files expkv.pdf
\unexpanded\expandafter{\ekv@name@set{#1}}%
\unexpanded\expandafter{\ekv@name@key{\detokenize{#2}}}%
}
-\ekv@expB@unbraceA{\def\ekv@name#1#2}{\ekv@name}
+\ekv@exparg{\def\ekv@name#1#2}{\ekv@name}
% \end{macrocode}
% \end{macro}
%
@@ -1340,16 +1347,16 @@ and the derived files expkv.pdf
}%
\unexpanded{\@gobble}%
}
-\ekv@expB@unbraceA{\protected\def\ekv@checkvalid#1#2}{\ekv@checkvalid}%
+\ekv@exparg{\protected\def\ekv@checkvalid#1#2}{\ekv@checkvalid}%
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvifdefined,\ekvifdefinedNoVal}
% And provide user-level macros to test whether a key is defined.
% \begin{macrocode}
-\ekv@expB@unbraceA{\ekv@expB@unbraceA{\def\ekvifdefined#1#2}}%
+\ekv@expargtwice{\def\ekvifdefined#1#2}%
{\expandafter\ekv@ifdefined\expandafter{\ekv@name{#1}{#2}}}
-\ekv@expB@unbraceA{\ekv@expB@unbraceA{\def\ekvifdefinedNoVal#1#2}}%
+\ekv@expargtwice{\def\ekvifdefinedNoVal#1#2}%
{\expandafter\ekv@ifdefined\expandafter{\ekv@name{#1}{#2}N}}
% \end{macrocode}
% \end{macro}
@@ -1372,27 +1379,27 @@ and the derived files expkv.pdf
{#1{\expandafter\let\csname#2\endcsname##3#3}}%
\protected\def\ekvletNoVal##1##2##3%
{#1{\expandafter\let\csname#2N\endcsname##3#3}}%
- \ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{%
- \protected\long\def\ekvdefunknown##1##2}}}%
+ \ekv@expargtwice{\protected\long\def\ekvdefunknown##1##2}%
{%
- \expandafter\ekv@expB@unbraceA@\expandafter
+ \romannumeral
+ \expandafter\ekv@exparg@\expandafter
{%
\expandafter\expandafter\expandafter
\def\expandafter\csname\ekv@name{##1}{}u\endcsname####1####2{##2}%
#3%
}%
- {\ekv@checkvalid{##1}.}%
+ {\ekv@zero\ekv@checkvalid{##1}.}%
}%
- \ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{%
- \protected\long\def\ekvdefunknownNoVal##1##2}}}%
+ \ekv@expargtwice{\protected\long\def\ekvdefunknownNoVal##1##2}%
{%
- \expandafter\ekv@expB@unbraceA@\expandafter
+ \romannumeral
+ \expandafter\ekv@exparg@\expandafter
{%
\expandafter\expandafter\expandafter
\def\expandafter\csname\ekv@name{##1}{}uN\endcsname####1{##2}%
#3%
}%
- {\ekv@checkvalid{##1}.}%
+ {\ekv@zero\ekv@checkvalid{##1}.}%
}%
\protected\def\ekvletkv##1##2##3##4%
{%
@@ -1441,16 +1448,14 @@ and the derived files expkv.pdf
}%
\unexpanded{\fi}%
}
-\ekv@expB@unbraceA{\protected\def\ekv@defsetmacro#1#2}{\ekv@defsetmacro}
+\ekv@exparg{\protected\def\ekv@defsetmacro#1#2}{\ekv@defsetmacro}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ekvifdefinedset}
% \begin{macrocode}
-\ekv@expB@unbraceA{\ekv@expB@unbraceA{\def\ekvifdefinedset#1}}%
- {%
- \expandafter\ekv@ifdefined\expandafter{\ekv@undefined@set{#1}}%
- }
+\ekv@expargtwice{\def\ekvifdefinedset#1}%
+ {\expandafter\ekv@ifdefined\expandafter{\ekv@undefined@set{#1}}}
% \end{macrocode}
% \end{macro}
%
@@ -1466,7 +1471,7 @@ and the derived files expkv.pdf
\begingroup
\def\ekvset#1#2{%
\endgroup
-\ekv@expB@unbraceA{\long\def\ekvset##1##2}%
+\ekv@exparg{\long\def\ekvset##1##2}%
{%
\expandafter\expandafter\expandafter
\ekv@set\expandafter\csname\ekv@undefined@set{##1}\endcsname
@@ -1515,14 +1520,8 @@ and the derived files expkv.pdf
% fast branching based on \TeX's argument grabbing rules and we don't have to
% split after the branching if the equal sign was there.
% \begin{macrocode}
-\long\def\ekv@eq@other##1=##2\ekv@mark##3%
- {%
- ##3##1\ekv@stop\ekv@mark##2%
- }
-\long\def\ekv@eq@active##1#2##2\ekv@mark##3%
- {%
- ##3##1\ekv@stop\ekv@mark##2%
- }
+\long\def\ekv@eq@other##1=##2\ekv@mark##3{##3##1\ekv@stop\ekv@mark##2}
+\long\def\ekv@eq@active##1#2##2\ekv@mark##3{##3##1\ekv@stop\ekv@mark##2}
% \end{macrocode}
% \end{macro}
%
@@ -1568,7 +1567,7 @@ and the derived files expkv.pdf
% needed to delimit |\ekv@set@pair|'s argument anyway, so we just leave it
% there.
% \begin{macrocode}
-\ekv@expB@unbraceA
+\ekv@exparg
{%
\long\def\ekv@set@eq@other@b
##1\ekv@nil\ekv@mark\ekv@set@eq@other@active\ekv@stop\ekv@mark
@@ -1585,7 +1584,7 @@ and the derived files expkv.pdf
% |##2| everything that remains until the first found other equal sign. It has
% to reinsert the equal sign and forward things to |\ekv@set@pair|.
% \begin{macrocode}
-\ekv@expB@unbraceA
+\ekv@exparg
{%
\long\def\ekv@set@eq@other@active
##1\ekv@stop##2\ekv@nil#2\ekv@mark
@@ -1610,11 +1609,9 @@ and the derived files expkv.pdf
% If an active equal sign was found in |\ekv@set@eq@active| we'll have to pass
% the now split \kv\ pair on to |\ekv@set@pair|.
% \begin{macrocode}
-\ekv@expB@unbraceA
+\ekv@exparg
{\long\def\ekv@set@eq@active@##1\ekv@stop##2\ekv@nil#2\ekv@mark\ekv@set@noeq}%
- {%
- \ekv@strip{##1}{\expandafter\ekv@set@pair\detokenize}\ekv@mark##2\ekv@nil
- }
+ {\ekv@strip{##1}{\expandafter\ekv@set@pair\detokenize}\ekv@mark##2\ekv@nil}
% \end{macrocode}
% \end{macro}
%
@@ -1635,21 +1632,16 @@ and the derived files expkv.pdf
\unexpanded\expandafter
{\ekv@strip{##1}{\expandafter\ekv@set@key\detokenize}\ekv@mark}%
}
-\ekv@expB@unbraceA
+\ekv@exparg
{%
\long\def\ekv@set@noeq
##1\ekv@nil\ekv@mark\ekv@set@eq@active@\ekv@stop\ekv@mark
}%
{\ekv@set@noeq}
-\def\ekv@set@was@blank##1%
- {%
- \def\ekv@set@was@blank
- \ekv@ifempty@A\ekv@ifempty@B
- \ekv@strip@a\ekv@mark####1\ekv@nil\ekv@mark##1##1\ekv@nil\ekv@stop
- ####2\ekv@mark
- {\ekv@set@other}%
- }
-\ekv@set@was@blank{ }
+\expandafter\def\expandafter\ekv@set@was@blank
+ \expandafter\ekv@ifempty@A\expandafter\ekv@ifempty@B
+ \ekv@strip{\ekv@mark##1}##2\ekv@mark
+ {\ekv@set@other}
% \end{macrocode}
% \end{macro}
%
@@ -1679,14 +1671,8 @@ and the derived files expkv.pdf
% One last thing we want to do for |\ekvset| is to provide macros that just
% smuggle stuff after |\ekvset|'s effects.
% \begin{macrocode}
-\long\def\ekvsneak##1##2\ekv@stop#1##3%
- {%
- ##2\ekv@stop#1{##3##1}%
- }
-\long\def\ekvsneakPre##1##2\ekv@stop#1##3%
- {%
- ##2\ekv@stop#1{##1##3}%
- }
+\long\def\ekvsneak##1##2\ekv@stop#1##3{##2\ekv@stop#1{##3##1}}
+\long\def\ekvsneakPre##1##2\ekv@stop#1##3{##2\ekv@stop#1{##1##3}}
% \end{macrocode}
% \end{macro}
%
@@ -1697,10 +1683,7 @@ and the derived files expkv.pdf
% |\unexpanded| here and there instead of other macros to stop the |\expanded|
% on our output.
% \begin{macrocode}
-\long\def\ekvparse##1##2##3%
- {%
- \ekv@parse##1##2\ekv@mark##3#1\ekv@stop#1%
- }
+\long\def\ekvparse##1##2##3{\ekv@parse{##1}{##2}\ekv@mark##3#1\ekv@stop#1}
% \end{macrocode}
% \end{macro}
%
@@ -1709,7 +1692,7 @@ and the derived files expkv.pdf
\long\def\ekv@parse##1##2##3#1%
{%
\ekv@gobble@from@mark@to@stop##3\ekv@endparse\ekv@stop
- \ekv@parse@other##1##2##3,\ekv@stop,%
+ \ekv@parse@other{##1}{##2}##3,\ekv@stop,%
}
% \end{macrocode}
% \end{macro}
@@ -1729,7 +1712,7 @@ and the derived files expkv.pdf
\ekv@gobble@from@mark@to@stop##3\ekv@endparse@other\ekv@stop
\ekv@eq@other##3\ekv@nil\ekv@mark\ekv@parse@eq@other@a
=\ekv@mark\ekv@parse@eq@active
- ##1##2%
+ {##1}{##2}%
\ekv@mark
}
% \end{macrocode}
@@ -1742,7 +1725,7 @@ and the derived files expkv.pdf
\ekv@eq@active##1\ekv@nil\ekv@mark\ekv@parse@eq@other@active
#2\ekv@mark\ekv@parse@eq@other@b
}
-\ekv@expB@unbraceA
+\ekv@exparg
{%
\long\def\ekv@parse@eq@other@b
##1\ekv@nil\ekv@mark\ekv@parse@eq@other@active\ekv@stop\ekv@mark
@@ -1754,7 +1737,7 @@ and the derived files expkv.pdf
%
% \begin{macro}[internal]{\ekv@parse@eq@other@active}
% \begin{macrocode}
-\ekv@expB@unbraceA
+\ekv@exparg
{%
\long\def\ekv@parse@eq@other@active
##1\ekv@stop##2\ekv@nil#2\ekv@mark
@@ -1772,11 +1755,9 @@ and the derived files expkv.pdf
\ekv@eq@active##1\ekv@nil\ekv@mark\ekv@parse@eq@active@
#2\ekv@mark\ekv@parse@noeq
}
-\ekv@expB@unbraceA
+\ekv@exparg
{\long\def\ekv@parse@eq@active@##1\ekv@stop##2#2\ekv@mark\ekv@parse@noeq}%
- {%
- \ekv@strip{##1}\ekv@parse@pair##2%
- }
+ {\ekv@strip{##1}\ekv@parse@pair##2}
% \end{macrocode}
% \end{macro}
%
@@ -1791,21 +1772,16 @@ and the derived files expkv.pdf
}%
\unexpanded\expandafter{\ekv@strip{##1}\ekv@parse@key}%
}
-\ekv@expB@unbraceA
+\ekv@exparg
{%
\long\def\ekv@parse@noeq
##1\ekv@nil\ekv@mark\ekv@parse@eq@active@\ekv@stop\ekv@mark
}%
{\ekv@parse@noeq}
-\def\ekv@parse@was@blank##1%
- {%
- \def\ekv@parse@was@blank
- \ekv@ifempty@A\ekv@ifempty@B
- \ekv@strip@a\ekv@mark####1\ekv@nil\ekv@mark##1##1\ekv@nil\ekv@stop
- \ekv@parse@key
- {\ekv@parse@other}%
- }
-\ekv@parse@was@blank{ }
+\expandafter\def\expandafter\ekv@parse@was@blank
+ \expandafter\ekv@ifempty@A\expandafter\ekv@ifempty@B
+ \ekv@strip{\ekv@mark##1}\ekv@parse@key
+ {\ekv@parse@other}
% \end{macrocode}
% \end{macro}
%
@@ -1821,24 +1797,22 @@ and the derived files expkv.pdf
%
% \begin{macro}[internal]{\ekv@parse@pair,\ekv@parse@pair@}
% \begin{macrocode}
-\ekv@expB@unbraceA{\long\def\ekv@parse@pair##1##2\ekv@nil}%
- {%
- \ekv@strip{##2}\ekv@parse@pair@{##1}%
- }
+\ekv@exparg{\long\def\ekv@parse@pair##1##2\ekv@nil}%
+ {\ekv@strip{##2}\ekv@parse@pair@{##1}}
\long\def\ekv@parse@pair@##1##2##3##4%
{%
\unexpanded{##4{##2}{##1}}%
- \ekv@parse@other##3##4%
+ \ekv@parse@other{##3}{##4}%
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[internal]{\ekv@parse@key}
% \begin{macrocode}
-\long\def\ekv@parse@key##1##2##3%
+\long\def\ekv@parse@key##1##2%
{%
\unexpanded{##2{##1}}%
- \ekv@parse@other##2##3%
+ \ekv@parse@other{##2}%
}
% \end{macrocode}
% \end{macro}
@@ -1861,8 +1835,7 @@ and the derived files expkv.pdf
\unexpanded{\ekvsneak{#2}}%
\unexpanded\expandafter{\ekvset{#1}{#3}}%
}
-\ekv@expB@unbraceA{\ekv@expB@unbraceA{\long\def\ekvsetSneaked#1#2#3}}%
- {\ekvsetSneaked}
+\ekv@expargtwice{\long\def\ekvsetSneaked#1#2#3}{\ekvsetSneaked}
% \end{macrocode}
% \end{macro}
%
@@ -1875,7 +1848,7 @@ and the derived files expkv.pdf
% switch out the set expandably, so this works similar to the |\ekvsneak| macros
% reading and reinserting the remainder of the \kv\ list.
% \begin{macrocode}
-\ekv@expB@unbraceA{\def\ekvchangeset#1}%
+\ekv@exparg{\def\ekvchangeset#1}%
{%
\expandafter\expandafter\expandafter
\ekv@changeset\expandafter\csname\ekv@undefined@set{#1}\endcsname\ekv@empty
@@ -1888,10 +1861,7 @@ and the derived files expkv.pdf
% leading |\ekv@empty| so that braces aren't stripped accidentally, but that
% will not hurt and just expand to nothing in one step.
% \begin{macrocode}
-\long\def\ekv@changeset#1#2\ekv@set@other#3%
- {%
- #2\ekv@set@other#1%
- }
+\long\def\ekv@changeset#1#2\ekv@set@other#3{#2\ekv@set@other#1}
% \end{macrocode}
% \end{macro}
%
@@ -1964,7 +1934,7 @@ and the derived files expkv.pdf
\fi
\ekv@set@pair@d#1%
}
-\ekv@expB@unbraceA{\long\def\ekv@set@pair@d#1#2#3}{\ekv@strip{#2}#1}
+\ekv@exparg{\long\def\ekv@set@pair@d#1#2#3}{\ekv@strip{#2}#1}
\long\def\ekv@set@pair@e\fi\ekv@set@pair@d#1#2#3{\fi#3}
% \end{macrocode}
% \end{macro}
@@ -2028,13 +1998,13 @@ and the derived files expkv.pdf
% \begin{macro}{\ekvsetdef}
% Provide a macro to define a shorthand to use |\ekvset| on a specified \set.
% To gain the maximum speed |\ekvset| is expanded twice by
-% |\ekv@expB@unbraceA| so that during runtime the macro storing the set name
+% |\ekv@exparg| so that during runtime the macro storing the set name
% is already built and one |\expandafter| doesn't have to be used.
% \begin{macrocode}
-\ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{%
-\protected\def\ekvsetdef#1#2}}}}%
+\ekv@expargtwice{\protected\def\ekvsetdef#1#2}%
{%
- \ekv@expB@unbraceA{\ekv@expB@unbraceA{\long\def#1##1}}%
+ \romannumeral
+ \ekv@exparg{\ekv@zero\ekv@exparg{\long\def#1##1}}%
{\ekvset{#2}{##1}}%
}
% \end{macrocode}
@@ -2044,16 +2014,16 @@ and the derived files expkv.pdf
% And do the same for |\ekvsetSneaked| in the two possible ways, with a fixed
% sneaked argument and with a flexible one.
% \begin{macrocode}
-\ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{%
-\protected\def\ekvsetSneakeddef#1#2}}}}%
+\ekv@expargtwice{\protected\def\ekvsetSneakeddef#1#2}%
{%
- \ekv@expB@unbraceA{\ekv@expB@unbraceA{\long\def#1##1##2}}%
+ \romannumeral
+ \ekv@exparg{\ekv@zero\ekv@exparg{\long\def#1##1##2}}%
{\ekvsetSneaked{#2}{##1}{##2}}%
}
-\ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{\ekv@expB@unbraceA{%
-\protected\def\ekvsetdefSneaked#1#2#3}}}}%
+\ekv@expargtwice{\protected\def\ekvsetdefSneaked#1#2#3}%
{%
- \ekv@expB@unbraceA{\ekv@expB@unbraceA{\long\def#1##1}}%
+ \romannumeral
+ \ekv@exparg{\ekv@zero\ekv@exparg{\long\def#1##1}}%
{\ekvsetSneaked{#2}{#3}{##1}}%
}
% \end{macrocode}
@@ -2090,12 +2060,9 @@ and the derived files expkv.pdf
% \begin{macrocode}
\long\def\ekv@err@common #1#2{\expandafter\ekv@err@common@\string#2{#1}}
\long\def\ekv@err@common@#1`#2' #3.#4#5{\ekv@err{#4 (`#5', set `#2')}}
-\ekv@expB@unbraceA{\long\def\ekv@err@unknown#1}%
- {\ekv@err@common{unknown key}{#1}}
-\ekv@expB@unbraceA{\long\def\ekv@err@noarg #1}%
- {\ekv@err@common{value forbidden}{#1}}
-\ekv@expB@unbraceA{\long\def\ekv@err@reqval #1}%
- {\ekv@err@common{value required}{#1}}
+\ekv@exparg{\long\def\ekv@err@unknown#1}{\ekv@err@common{unknown key}{#1}}
+\ekv@exparg{\long\def\ekv@err@noarg #1}{\ekv@err@common{value forbidden}{#1}}
+\ekv@exparg{\long\def\ekv@err@reqval #1}{\ekv@err@common{value required}{#1}}
% \end{macrocode}
% \end{macro}
%
diff --git a/macros/generic/expkv/expkv.pdf b/macros/generic/expkv/expkv.pdf
index 4396ddfee2..ba39085660 100644
--- a/macros/generic/expkv/expkv.pdf
+++ b/macros/generic/expkv/expkv.pdf
Binary files differ
diff --git a/macros/latex/contrib/froufrou/LICENSE b/macros/latex/contrib/froufrou/LICENSE
new file mode 100644
index 0000000000..dea471c70c
--- /dev/null
+++ b/macros/latex/contrib/froufrou/LICENSE
@@ -0,0 +1,11 @@
+Copyright 2020 Nelson Lago <lago@ime.usp.br>
+
+This work may be distributed and/or modified under the conditions of the
+LaTeX Project Public License, either version 1.3 of this license or (at
+your option) any later version. The latest version of this license can be
+found at http://www.latex-project.org/lppl.txt and version 1.3 or later
+is part of all distributions of LaTeX version 2005/12/01 or later.
+
+This work has the LPPL maintenance status `maintained'.
+
+The Current Maintainer of this work is Nelson Lago <lago@ime.usp.br>.
diff --git a/macros/latex/contrib/froufrou/README.md b/macros/latex/contrib/froufrou/README.md
new file mode 100644
index 0000000000..2dbf650211
--- /dev/null
+++ b/macros/latex/contrib/froufrou/README.md
@@ -0,0 +1,13 @@
+# froufrou - visual section separators (a.k.a. anonymous sections) for LaTeX
+
+This package provides fancy separators, which are visual cues that
+indicate a change of subject or context without actually starting
+a new chapter or section.
+
+Code etc: <https://gitlab.com/lago/froufrou>
+
+Copyright 2020 Nelson Lago <lago@ime.usp.br>
+
+This work may be distributed and/or modified under the conditions of the
+LaTeX Project Public License, either version 1.3 of this license or (at
+your option) any later version.
diff --git a/macros/latex/contrib/froufrou/froufrou.dtx b/macros/latex/contrib/froufrou/froufrou.dtx
new file mode 100644
index 0000000000..bce65ae076
--- /dev/null
+++ b/macros/latex/contrib/froufrou/froufrou.dtx
@@ -0,0 +1,316 @@
+% \iffalse meta-comment
+% Copyright 2020 Nelson Lago <lago@ime.usp.br>
+%
+% This work may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License, either version 1.3 of this license or (at
+% your option) any later version. The latest version of this license can be
+% found at http://www.latex-project.org/lppl.txt and version 1.3 or later
+% is part of all distributions of LaTeX version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Nelson Lago <lago@ime.usp.br>.
+%
+% \fi
+% \iffalse
+%
+%<package>\NeedsTeXFormat{LaTeX2e}[2015/01/01]
+%<package>\ProvidesPackage{froufrou}[2020/12/22 1.2 Visual section separator]
+%
+%<*driver>
+
+\documentclass{ltxdoc}
+
+\usepackage[hyperref,svgnames,x11names,table]{xcolor}
+\usepackage{url}
+\urlstyle{sf}
+\usepackage{hyperref}
+\hypersetup{
+ pdfborder={0 0 .6},
+ pdfborderstyle={/S/U/W .6},
+ urlbordercolor=DodgerBlue,
+ citebordercolor=White,
+ linkbordercolor=White,
+ filebordercolor=White,
+}
+
+\usepackage{froufrou}
+
+\usepackage{libertinus}
+\usepackage[scale=.85]{sourcecodepro}
+
+%%\EnableCrossrefs
+%%\CodelineIndex
+\RecordChanges
+
+\OnlyDescription
+
+\begin{document}
+\DocInput{froufrou.dtx}
+\end{document}
+
+%</driver>
+%
+% \fi
+%
+% \CheckSum{0}
+%
+% \changes{v1.0}{2019/04/24}{Prerelease}
+% \changes{v1.1}{2020/02/03}{Prerelease}
+% \changes{v1.2}{2020/12/22}{First public version}
+%
+% \GetFileInfo{froufrou.sty}
+%
+% \title{The \textsf{froufrou} package\thanks{This document
+% corresponds to \textsf{froufrou}~\fileversion, dated~\filedate.}}
+%
+% \author{
+% Nelson Lago\\
+% \texttt{lago@ime.usp.br}\\
+% ~\\
+% \url{https://gitlab.com/lago/froufrou}
+% }
+%
+% \maketitle
+%
+% \begin{abstract}
+%
+% This package provides fancy separators, which are visual cues that
+% indicate a change of subject or context without actually starting
+% a new chapter or section.
+%
+% \end{abstract}
+%
+% \section{Introduction}
+%
+% This package allows the user to create fancy separators that visually
+% indicate text subdivisions without a title, i.e., they are similar to
+% \verb|\section| but do not provide a name to the new section. Apparently,
+% there is no definite name for such separators; they may be regarded as
+% thought breaks or anonymous sections, but often borrow their name from
+% the ornament that embodies them, such as asterism, fleuron, or dinkus.
+% An example:
+%
+% \froufrou
+%
+% Such separators never appear at the top of the page (that would be
+% confusing), but may appear at the bottom. They should work equally
+% well with one or two-column text and with single or doublespacing.
+% The package offers a few predefined ornaments to be used as separators,
+% but the user may create others.
+%
+% \section{Usage}
+%
+% After \verb|\usepackage{froufrou}|, just call \verb|\froufrou| to create
+% a subdivision. By default, the separator behaves like \verb|\section|,
+% suppressing indentation in the following paragraph. With \verb|\froufrou*|,
+% this feature is disabled and the following paragraph is indented normally.
+%
+% You may select a different separator appearance either by
+% supplying the name of a predefined ornament as a package
+% option (\verb|\usepackage[ornament]{froufrou}|) or by calling
+% \verb|\setfroufrou{ornament}| anywhere in the document. You may
+% also use \verb|\froufrou[ornament]| to only affect that specific
+% separator. \verb|ornament| is one of:
+%
+% \makeatletter
+% \begin{description}
+%
+% \item[fleuron,] the default\footnote{From the \verb|fancyhdr| docs.}: \quad\@froufrouFleuron
+%
+% \item[simplefleuron,] similar to the default, but without the side lines: \quad\@froufrouSimpleFleuron
+%
+% \item[asterism,] three asterisks forming a triangle\footnote{
+% From \verb|symbols-a4| (search for ``asterism'').}: \quad\@froufrouAsterism
+%
+% \item[tightasterism,] similar, but with tighter spacing: \quad\@froufrouTightAsterism
+%
+% \item[trueasterism,] also similar, but using unicode character
+% U+2042\footnote{This only works with a unicode engine
+% (luatex, xetex) and with a font that actually provides the
+% glyph (such as libertinus or libertine).}: \quad\@froufrouTrueAsterism
+%
+% \item[dinkus,] three asterisks forming a line: \quad\@froufrouDinkus
+%
+% \end{description}
+% \makeatother
+%
+% Beyond the predefined ornaments, you may also use
+% \verb|\setfroufrou{SOMETHING}| or \verb|\froufrou[SOMETHING]|
+% to make \verb|SOMETHING| be the separator. However, please note
+% that \verb|\usepackage[SOMETHING]{froufrou}| does \emph{not} work!
+%
+% \section{See also}
+%
+% \begin{itemize}
+% \item \url{http://tug.org/TUGboat/tb32-2/tb101glister.pdf} ;
+% \item The \verb|pgfornament| package, which may aid in creating separators;
+% \item The \verb|novel| class, which offers the somewhat similar \verb|\ChapterDeco| command;
+% \item The \verb|memoir| class, which offers the somewhat similar \verb|\fancybreak| command;
+% \end{itemize}
+%
+% \StopEventually{\PrintChanges}
+%
+% \section{The implementation}
+%
+% \begin{macrocode}
+
+\RequirePackage{etoolbox}
+\RequirePackage{expl3}
+
+% .1\textwidth works well for one and two-column text.
+\RequirePackage{fourier-orns}
+\newcommand\@froufrouFleuron{%
+ \bgroup
+ \footnotesize
+ \rule[.7mm]{.1\textwidth}{0.5pt}%
+ \enspace\,%
+ \decofourleft\decotwo\decofourright
+ \enspace\,%
+ \rule[.7mm]{.1\textwidth}{0.5pt}%
+ \egroup
+}
+
+\newcommand\@froufrouSimpleFleuron{%
+ \bgroup
+ \footnotesize
+ \decofourleft\decotwo\decofourright
+ \egroup
+}
+
+\newcommand{\@froufrouTightAsterism}{%
+ \bgroup
+ \smash{%
+ \raisebox{-.5ex}{%
+ \setlength{\tabcolsep}{-.5pt}%
+ \begin{tabular}{@{}cc@{}}%
+ \multicolumn2c*\\[-2ex]*&*%
+ \end{tabular}%
+ }%
+ }%
+ \egroup
+}
+
+\newcommand{\@froufrouAsterism}{%
+ \bgroup
+ \smash{%
+ \raisebox{-.5ex}{%
+ \setlength{\tabcolsep}{0pt}%
+ \begin{tabular}{@{}cc@{}}%
+ \multicolumn2c*\\[-1.8ex]*&*%
+ \end{tabular}%
+ }%
+ }%
+ \egroup
+}
+
+% Unicode character U+2042 (\char"2042), only with a unicode engine
+% (luatex/xetex) and a font that has this glyph (such as libertinus
+% or libertine)
+\newcommand\@froufrouTrueAsterism{⁂}
+
+\newcommand{\@froufrouDinkus}{\relax*\quad*\quad*}
+
+\ExplSyntaxOn
+\newcommand\setfroufrou[1]{%
+ \str_case:nnF{#1}{
+ {}{\relax}
+ {fleuron}{\def\@froufrouOrnament{\@froufrouFleuron}}
+ {simplefleuron}{\def\@froufrouOrnament{\@froufrouSimpleFleuron}}
+ {asterism}{\def\@froufrouOrnament{\@froufrouAsterism}}
+ {tightasterism}{\def\@froufrouOrnament{\@froufrouTightAsterism}}
+ {trueasterism}{\def\@froufrouOrnament{\@froufrouTrueAsterism}}
+ {dinkus}{\def\@froufrouOrnament{\@froufrouDinkus}}%
+ }{\def\@froufrouOrnament{#1}}%
+}
+\ExplSyntaxOff
+
+% I see no reason to make these different, but feel free to change this :)
+\def\@froufrouspacebefore{\vskip 22pt plus 7pt minus 5pt}
+\def\@froufrouspaceafter{\@froufrouspacebefore}
+
+% The starred form means "indent the first line of the next paragraph"
+% (\if@afterindent is read by \@afterheading)
+\newcommand{\froufrou}{%
+ \@ifstar{\@afterindenttrue\@realfroufrou}{\@afterindentfalse\@realfroufrou}%
+}
+
+% For compatibility with older versions of this package
+\newcommand\frufru{\froufrou}
+
+\newcommand{\@realfroufrou}[1][]{%
+ % Make sure we left horizontal mode.
+ \nopagebreak[4]\par
+
+ \nopagebreak[4]\@froufrouspacebefore\nopagebreak[4]
+
+ % Start a new group to (1) reset \doublespacing, \parskip, and
+ % \baselineskip, so spacing is independent from the previous text
+ % settings and (2) so that using #1 to change the ornament only
+ % affects the current call. Then, start yet another group only
+ % for the ornament because font size changes in it should not
+ % affect spacing either.
+ \bgroup
+ \setfroufrou{#1}%
+ \normalsize
+ \ifdefvoid{\setstretch}{}{\setstretch{\setspace@singlespace}}% normally 1
+ \setlength{\parskip}{0pt}
+ \noindent\centering\bgroup\@froufrouOrnament\egroup\par
+ \egroup
+
+ \nopagebreak[4]\@froufrouspaceafter\nopagebreak[4]
+
+ % Next paragraph's \doublespacing, \baselineskip, and \parskip
+ % should not affect spacing.
+ \@froufrouFixSpacingAfter
+
+ % Breaking after the separator is acceptable as a last resort. Since
+ % we use a lot of vertical space before/after it, not allowing this
+ % break might lead to poor results in some cases.
+ \nopagebreak[3]
+
+ % Emulate the behavior of \section, \subsection etc: prevent
+ % the first line of the next paragraph from being indented
+ % and absolutely forbid a club line in the next paragraph.
+ \@afterheading
+}
+
+\newcommand\@froufrouFixSpacingAfter{
+ % The next \par will add \parskip and \baselineskip. We want to
+ % (1) eliminate \parskip so that spacing does not change if it
+ % is nonzero and (2) add the "normal" \baselineskip, even if the
+ % text is set using \doublespacing. These adjustments may be off
+ % if font size, \parskip or \baselineskip are changed before the
+ % next paragraph.
+
+ \nopagebreak[4]\vskip -\parskip
+
+ \ifdefvoid{\setstretch}
+ {}
+ {
+ \bgroup
+ % \singlespacing may add an extra \baselineskip; let's
+ % avoid surprises and use \setstrech instead.
+ \setstretch {\setspace@singlespace}% normally 1
+ \nopagebreak[4]\vskip \baselineskip
+ \egroup
+
+ \nopagebreak[4]\vskip -\baselineskip
+ }
+}
+
+% Trying to accept a custom ornament as a package option is not such a
+% great idea: first, it has to be expandable; second, this may become
+% a problem if we want to add more options to the class in the future.
+\DeclareOption{fleuron}{\setfroufrou{fleuron}}
+\DeclareOption{simplefleuron}{\setfroufrou{simplefleuron}}
+\DeclareOption{asterism}{\setfroufrou{asterism}}
+\DeclareOption{tightasterism}{\setfroufrou{tightasterism}}
+\DeclareOption{trueasterism}{\setfroufrou{trueasterism}}
+\DeclareOption{dinkus}{\setfroufrou{dinkus}}
+\DeclareOption*{\PackageWarning{froufrou}{Unknown option `\CurrentOption'}}
+\ExecuteOptions{fleuron}
+\ProcessOptions\relax
+
+% \end{macrocode}
+% \Finale
diff --git a/macros/latex/contrib/froufrou/froufrou.ins b/macros/latex/contrib/froufrou/froufrou.ins
new file mode 100644
index 0000000000..153a5a04fc
--- /dev/null
+++ b/macros/latex/contrib/froufrou/froufrou.ins
@@ -0,0 +1,50 @@
+%% Copyright 2020 Nelson Lago <lago@ime.usp.br>
+%%
+%% This work may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License, either version 1.3 of this license or (at
+%% your option) any later version. The latest version of this license can be
+%% found at http://www.latex-project.org/lppl.txt and version 1.3 or later
+%% is part of all distributions of LaTeX version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Nelson Lago <lago@ime.usp.br>.
+
+\input docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\usedir{tex/latex/froufrou}
+
+\preamble
+Copyright 2020 Nelson Lago <lago@ime.usp.br>
+
+This work may be distributed and/or modified under the conditions of the
+LaTeX Project Public License, either version 1.3 of this license or (at
+your option) any later version. The latest version of this license can be
+found at http://www.latex-project.org/lppl.txt and version 1.3 or later
+is part of all distributions of LaTeX version 2005/12/01 or later.
+
+This work has the LPPL maintenance status `maintained'.
+
+The Current Maintainer of this work is Nelson Lago <lago@ime.usp.br>.
+
+\endpreamble
+
+\generate{\file{froufrou.sty}{\from{froufrou.dtx}{package}}}
+
+\obeyspaces
+\Msg{****************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the *}
+\Msg{* following file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* froufrou.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file *}
+\Msg{* froufrou.dtx through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{****************************************************}
+
+\endbatchfile
diff --git a/macros/latex/contrib/froufrou/froufrou.pdf b/macros/latex/contrib/froufrou/froufrou.pdf
new file mode 100644
index 0000000000..fb3816384c
--- /dev/null
+++ b/macros/latex/contrib/froufrou/froufrou.pdf
Binary files differ