summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-01-18 03:01:07 +0000
committerNorbert Preining <norbert@preining.info>2022-01-18 03:01:07 +0000
commit42225b2641eab592f67f238c364b237ee036bf0a (patch)
tree80da1bff81f487c45384ea40a060c77a372583dd /macros
parenta98801f61d66bae07d8786d2891bed0bece7d96e (diff)
CTAN sync 202201180301
Diffstat (limited to 'macros')
-rw-r--r--macros/latex/contrib/apa7/README.txt2
-rw-r--r--macros/latex/contrib/apa7/apa7.dtx51
-rw-r--r--macros/latex/contrib/apa7/apa7.ins8
-rw-r--r--macros/latex/contrib/apa7/apa7.pdfbin555774 -> 555936 bytes
-rw-r--r--macros/latex/contrib/apa7/samples/longsample.pdfbin204050 -> 204049 bytes
-rw-r--r--macros/latex/contrib/apa7/samples/shortsample.pdfbin69708 -> 69692 bytes
-rw-r--r--macros/latex/contrib/bewerbung/README6
-rw-r--r--macros/latex/contrib/bewerbung/README_DE6
-rw-r--r--macros/latex/contrib/bewerbung/argetabelle-example.pdfbin41294 -> 43179 bytes
-rw-r--r--macros/latex/contrib/bewerbung/bewerbung-example.pdfbin148575 -> 144541 bytes
-rw-r--r--macros/latex/contrib/bewerbung/bewerbung.dtx96
-rw-r--r--macros/latex/contrib/bewerbung/bewerbung.ins4
-rw-r--r--macros/latex/contrib/bewerbung/bewerbung.pdfbin693654 -> 765001 bytes
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.bbx6
-rw-r--r--macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.cbx2
-rw-r--r--macros/latex/contrib/dbshow/dbshow.dtx3156
-rw-r--r--macros/latex/contrib/dbshow/dbshow.pdfbin440283 -> 602868 bytes
-rw-r--r--macros/latex/contrib/easybook/easybook.dtx62
-rw-r--r--macros/latex/contrib/easybook/easybook.pdfbin595578 -> 595806 bytes
-rw-r--r--macros/latex/contrib/easybook/easybook.tex14
-rw-r--r--macros/latex/contrib/kanbun/README.md24
-rw-r--r--macros/latex/contrib/kanbun/kanbun-example.pdfbin0 -> 45616 bytes
-rw-r--r--macros/latex/contrib/kanbun/kanbun-example.tex44
-rw-r--r--macros/latex/contrib/kanbun/kanbun.lua224
-rw-r--r--macros/latex/contrib/kanbun/kanbun.pdfbin0 -> 376249 bytes
-rw-r--r--macros/latex/contrib/kanbun/kanbun.sty317
-rw-r--r--macros/latex/contrib/kanbun/kanbun.tex301
-rw-r--r--macros/latex/contrib/llncs/README.md40
-rw-r--r--macros/latex/contrib/llncs/history.txt144
-rw-r--r--macros/latex/contrib/llncs/llncs.cls1218
-rw-r--r--macros/latex/contrib/llncs/llncsdoc.pdfbin0 -> 218741 bytes
-rw-r--r--macros/latex/contrib/llncs/llncsdoc.tex422
-rw-r--r--macros/latex/contrib/llncs/splncs04.bst1548
33 files changed, 6679 insertions, 1016 deletions
diff --git a/macros/latex/contrib/apa7/README.txt b/macros/latex/contrib/apa7/README.txt
index ed40d4d6dd..6a5bee83b0 100644
--- a/macros/latex/contrib/apa7/README.txt
+++ b/macros/latex/contrib/apa7/README.txt
@@ -3,7 +3,7 @@
apa7 - A LaTeX class for formatting documents in compliance with the
American Psychological Association's Publication Manual, 7th edition
-Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License (LPPL), either
diff --git a/macros/latex/contrib/apa7/apa7.dtx b/macros/latex/contrib/apa7/apa7.dtx
index 3e572a7393..045adf9b03 100644
--- a/macros/latex/contrib/apa7/apa7.dtx
+++ b/macros/latex/contrib/apa7/apa7.dtx
@@ -4,11 +4,11 @@
% %
% CHANGE THESE VALUES WITH EACH NEW RELEASE: %
% %
-%<class>\ProvidesClass{apa7}[2021/11/21 v2.14 APA formatting (7th edition)]
+%<class>\ProvidesClass{apa7}[2022/01/03 v2.15 APA formatting (7th edition)]
% %
%<*internal> %
-\def\apaSevenVersionDate{2021/11/21}
-\def\apaSevenVersionNumber{2.14}
+\def\apaSevenVersionDate{2022/01/03}
+\def\apaSevenVersionNumber{2.15}
% %
% %
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -20,7 +20,7 @@
apa7 - A LaTeX class for formatting documents in compliance with the
American Psychological Association's Publication Manual, 7th edition
-Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License (LPPL), either
@@ -68,7 +68,7 @@ Installation Notes:
apa7 - A LaTeX class for formatting documents in compliance with the
American Psychological Association's Publication Manual, 7th edition
-Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License (LPPL), either
@@ -88,7 +88,7 @@ by, the American Psychological Association.
\endpreamble
\postamble
-Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License (LPPL), either
@@ -286,6 +286,8 @@ and the derived files apa7.ins,
%
% \changes{v2.14}{2021/08/08}{Added Spanish localization. Fixed compatibility with Version 4.0 of flushend.sty. Clarify installation in readme. }
%
+% \changes{v2.15}{2022/01/03}{Spacing updated to more closely match APA 7th Edition Manual.}
+%
% \begin{abstract}
% The \textit{Publication Manual} of the American Psychological
% Association is widely used in the social sciences. The most
@@ -369,10 +371,8 @@ and the derived files apa7.ins,
% main one.
% \item \DescribeMacro{donotrepeattitle}|donotrepeattitle|: Suppress the title above the
% introduction (in case a different title is desired).
-% \item \DescribeMacro{noextraspace}|noextraspace|: In |man| and |stu| mode,
-% removes some of the vertical space between certain elements (e.g.,
-% headers and text) in an attempt to more closely resemble true
-% double-spacing (use at your own risk).
+% \item \DescribeMacro{noextraspace}|noextraspace|: Removed option in version 2.15
+% in an attempt to more closely match APA 7th edition guidelines (will throw error if used).
% \item \DescribeMacro{floatsintext}|floatsintext|: In |man| and |stu| mode,
% integrates floats (tables and figures) within the body of the text
% instead of postponing them until after the reference list.
@@ -1142,7 +1142,7 @@ and the derived files apa7.ins,
% remove extra space around headings, etc., in man mode
\DeclareOption{noextraspace}{%
- \def\def@noextraspace{\@noextraspacemode}
+ \ClassError{apa7}{Option removed: no longer uses as of version 2.15}{Spacing updated to more closely match APA 7th Edition Manual}
}
% suppress the title at the introduction (in case a different title is desired)
@@ -1755,14 +1755,12 @@ and the derived files apa7.ins,
\newskip\e@level@two@skip \e@level@two@skip=1.5ex plus .6ex minus .1ex
\newskip\b@level@three@skip \b@level@three@skip=2.0ex plus .8ex minus .2ex
\newskip\e@level@three@skip \e@level@three@skip=1.5ex plus .6ex minus .1ex
-\newskip\b@level@four@skip \b@level@four@skip=1.8ex plus .8ex minus .2ex
-\newskip\e@level@four@skip \e@level@four@skip=1.5ex plus .6ex minus .1ex
-\newskip\b@level@five@skip \b@level@five@skip=1.8ex plus .8ex minus .2ex
-\newskip\e@level@five@skip \e@level@five@skip=0ex
+\newskip\b@level@four@skip \b@level@four@skip=0\baselineskip \@plus 0.2ex \@minus 0.2ex
+\newskip\e@level@four@skip \e@level@four@skip=-0.5em
+\newskip\b@level@five@skip \b@level@five@skip=0\baselineskip \@plus 0.2ex \@minus 0.2ex
+\newskip\e@level@five@skip \e@level@five@skip=-0.5em
\ifapamodeman{%
- \@ifundefined{def@noextraspace}{}{%
- % redefine the vertical section spacing
\b@level@one@skip=0.2\baselineskip \@plus 0.2ex \@minus 0.2ex
\e@level@one@skip=0.2\baselineskip \@plus .2ex
\b@level@two@skip=0.2\baselineskip \@plus 0.2ex \@minus 0.2ex
@@ -1770,14 +1768,11 @@ and the derived files apa7.ins,
\b@level@three@skip=0.2\baselineskip \@plus 0.2ex \@minus 0.2ex
\e@level@three@skip=0.2\baselineskip \@plus 0.2ex
\b@level@four@skip=0\baselineskip \@plus 0.2ex \@minus 0.2ex
- \e@level@four@skip=-\z@
+ \e@level@four@skip=-0.5em
\b@level@five@skip=0\baselineskip \@plus 0.2ex \@minus 0.2ex
- \e@level@five@skip=0ex
- }
+ \e@level@five@skip=-0.5em
}{}
-
-
%========== APA Section heading & seriation, adapted from class apa6e
% % Below is the license statement from the apa6e class, from which a
@@ -1833,13 +1828,13 @@ and the derived files apa7.ins,
{\normalfont\normalsize\bfseries\itshape}}
\renewcommand{\paragraph}{\@startsection{paragraph}{4}{\parindent}%
- {0\baselineskip \@plus 0.2ex \@minus 0.2ex}%
- {-1em}%
+ {\b@level@four@skip}%
+ {\e@level@four@skip}%
{\normalfont\normalsize\bfseries\typesectitle}}
\renewcommand{\subparagraph}[1]{\@startsection{subparagraph}{5}{1em}%
- {0\baselineskip \@plus 0.2ex \@minus 0.2ex}%
- {-\z@\relax}%
+ {\b@level@five@skip}%
+ {\e@level@five@skip}%
{\normalfont\normalsize\bfseries\itshape\hspace{\parindent}{#1}\textit{\addperi}}{\relax}}
% make the References section non-boldface
@@ -2601,9 +2596,7 @@ and the derived files apa7.ins,
\vspace*{4\baselineskip}
\textbf\@title%
\ifapamodeman{%
- \@ifundefined{def@noextraspace}{%
- \vspace{\baselineskip}\\
- }{\\}
+ \vspace{\baselineskip}\\
}{%
\vspace{\baselineskip}\\
}
diff --git a/macros/latex/contrib/apa7/apa7.ins b/macros/latex/contrib/apa7/apa7.ins
index 3235d95787..ff008168cb 100644
--- a/macros/latex/contrib/apa7/apa7.ins
+++ b/macros/latex/contrib/apa7/apa7.ins
@@ -10,7 +10,7 @@
%% apa7 - A LaTeX class for formatting documents in compliance with the
%% American Psychological Association's Publication Manual, 7th edition
%%
-%% Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+%% Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License (LPPL), either
@@ -36,7 +36,7 @@
apa7 - A LaTeX class for formatting documents in compliance with the
American Psychological Association's Publication Manual, 7th edition
-Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License (LPPL), either
@@ -56,7 +56,7 @@ by, the American Psychological Association.
\endpreamble
\postamble
-Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License (LPPL), either
@@ -124,7 +124,7 @@ and the derived files apa7.ins,
}
\endbatchfile
%%
-%% Copyright (C) 2021 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
+%% Copyright (C) 2022 by Daniel A. Weiss <daniel.weiss.led at gmail.com>
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License (LPPL), either
diff --git a/macros/latex/contrib/apa7/apa7.pdf b/macros/latex/contrib/apa7/apa7.pdf
index d3e53c5c89..0afc73cd3c 100644
--- a/macros/latex/contrib/apa7/apa7.pdf
+++ b/macros/latex/contrib/apa7/apa7.pdf
Binary files differ
diff --git a/macros/latex/contrib/apa7/samples/longsample.pdf b/macros/latex/contrib/apa7/samples/longsample.pdf
index 3d474216f2..a259e67721 100644
--- a/macros/latex/contrib/apa7/samples/longsample.pdf
+++ b/macros/latex/contrib/apa7/samples/longsample.pdf
Binary files differ
diff --git a/macros/latex/contrib/apa7/samples/shortsample.pdf b/macros/latex/contrib/apa7/samples/shortsample.pdf
index 370ffb18af..77b7232966 100644
--- a/macros/latex/contrib/apa7/samples/shortsample.pdf
+++ b/macros/latex/contrib/apa7/samples/shortsample.pdf
Binary files differ
diff --git a/macros/latex/contrib/bewerbung/README b/macros/latex/contrib/bewerbung/README
index f30014d41b..ac69f80e69 100644
--- a/macros/latex/contrib/bewerbung/README
+++ b/macros/latex/contrib/bewerbung/README
@@ -7,11 +7,11 @@
printing a table with the latest applications that can be shown to the german authorities. The
data of the applications can be edited in a simple csv file.
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
- Version: 1.2
- Last Change: 2020-11-24
+ Version: 1.3
+ Last Change: 2022-01-17
Current Maintainer: André Hilbig
mail@andrehilbig.de
- https://www.andrehilbig.de/index.cgi/Publications/Bewerbung
+ https://git.andrehilbig.de/ahilbig/vorlagebewerbung
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
This work may be distributed and/or modified under the
diff --git a/macros/latex/contrib/bewerbung/README_DE b/macros/latex/contrib/bewerbung/README_DE
index d28d486fad..17b7b3d69b 100644
--- a/macros/latex/contrib/bewerbung/README_DE
+++ b/macros/latex/contrib/bewerbung/README_DE
@@ -8,11 +8,11 @@
vorgelegt werden kann. Die Daten der Bewerbungsversuche werden in einer simplen csv-Datei
verwaltet.
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
- Version: 1.2
- Last Change 2020-11-24
+ Version: 1.3
+ Last Change 2022-01-17
Current Maintainer: André Hilbig
mail@andrehilbig.de
- https://www.andrehilbig.de/index.cgi/Publications/Bewerbung
+ https://git.andrehilbig.de/ahilbig/vorlagebewerbung
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
This work may be distributed and/or modified under the
diff --git a/macros/latex/contrib/bewerbung/argetabelle-example.pdf b/macros/latex/contrib/bewerbung/argetabelle-example.pdf
index 7d795ce9e7..9bcbc0c7c5 100644
--- a/macros/latex/contrib/bewerbung/argetabelle-example.pdf
+++ b/macros/latex/contrib/bewerbung/argetabelle-example.pdf
Binary files differ
diff --git a/macros/latex/contrib/bewerbung/bewerbung-example.pdf b/macros/latex/contrib/bewerbung/bewerbung-example.pdf
index 5a563556ea..70b68fd5c1 100644
--- a/macros/latex/contrib/bewerbung/bewerbung-example.pdf
+++ b/macros/latex/contrib/bewerbung/bewerbung-example.pdf
Binary files differ
diff --git a/macros/latex/contrib/bewerbung/bewerbung.dtx b/macros/latex/contrib/bewerbung/bewerbung.dtx
index 3081b10a14..4ccf2e27cd 100644
--- a/macros/latex/contrib/bewerbung/bewerbung.dtx
+++ b/macros/latex/contrib/bewerbung/bewerbung.dtx
@@ -1,20 +1,20 @@
%\iffalse
% bewerbung.dtx generated using makedtx version 0.94b (c) Nicola Talbot
% Command line args:
+% -date "2022-01-17:16:26:37 -- Version 1.3"
+% -comment "neueBewerbung.sh"
+% -comment "config.inc=>config.inc"
+% -author "André Hilbig, mail@andrehilbig.de"
+% -codetitle "Implementation"
+% -macrocode "neueBewerbung.sh"
% -src "(.*)\.sty=>\1.sty"
% -src "(.*)\.cls=>\1.cls"
% -src "neueBewerbung.sh=>neueBewerbung.sh"
% -src "(.*)\.inc=>\1.inc"
-% -codetitle "Implementation"
-% -author "André Hilbig, mail@andrehilbig.de"
% -doc "../dokumentation.tex"
% -setambles "neueBewerbung.sh=>\nopreamble\nopostamble"
-% -date "2020-11-24:11:30:14 -- Version 1.2"
-% -macrocode "neueBewerbung.sh"
-% -comment "neueBewerbung.sh"
-% -comment "config.inc=>config.inc"
% bewerbung
-% Created on 2020-11-24:11:30:14 -- Version 1.2/11/24 11:30
+% Created on 2022-01-17:16:26:37 -- Version 1.3/1/17 16:26
%\fi
%\iffalse
%<*package>
@@ -37,7 +37,7 @@
%\fi
% \iffalse
% Doc-Source file to use with LaTeX2e
-% Copyright (C) 2020-11-24:11:30:14 -- Version 1.2 André Hilbig, mail@andrehilbig.de, all rights reserved.
+% Copyright (C) 2022-01-17:16:26:37 -- Version 1.3 André Hilbig, mail@andrehilbig.de, all rights reserved.
% \fi
% \iffalse
%<*driver>
@@ -220,7 +220,7 @@
\xspaceaddexceptions{\guillemotright,\guillemotleft}
-\CheckSum{2181}
+\CheckSum{2158}
\begin{document}
@@ -233,8 +233,8 @@
% \LaTeX-Klassen und -Pakete zum Setzen schöner Bewerbungsmappen und einer
% Übersichtstabelle zur Dokumentation der Bewerbungsversuche}
% \author{Andr\'e Hilbig \\ \texttt{mail@andrehilbig.de} \\
-% \url{http://www.andrehilbig.de/index.cgi/Publications/Bewerbung}}
-% \date{2020-11-24}
+% \url{https://git.andrehilbig.de/ahilbig/vorlagebewerbung}}
+% \date{2022-01-17}
% \maketitle
% \begin{abstract}
% \foreignlanguage{english}{
@@ -325,11 +325,6 @@
% \item Satz in der Dokumentation überarbeitet
% \item Kontaktdaten in den READMEs korrigiert
% \end{itemize}
-% \item[v1.2]
-% \begin{itemize}
-% \item Anpassungen an neuere \LaTeX Versionen durchgeführt
-% \item Kleinere Anpassungen an die Titelseite
-% \end{itemize}
% \end{description}
%
% \section{Installation}
@@ -442,6 +437,11 @@
% Der Befehl |\Sta|\marg{Staatsangehörigkeit} legt die Staatsangehörigkeit fest und
% |\GebDatum|\marg{Geburtsdatum} definiert das Geburtsdatum.
%
+% \DescribeMacro{\LebenslaufTitel}
+% Der Befehl |\LebenslaufTitel|\marg{Titel} ändert den Titel des Lebenslauf. Standardmäßig
+% wird \textit{Curriculum Vitae} verwendet. So kann bspw. auch \textit{Lebenslauf} als Titel
+% gesetzt werden.
+%
% \DescribeMacro{\ID}
% Durch das Makro |\ID|\marg{Identifikation} wird die Nummer der aktuellen Bewerbung
% angegeben. Damit werden die Daten der aktuellen Bewerbung aus einer Datei ausgelesen.
@@ -453,8 +453,7 @@
% Der Klasse |bewerbung| kann die Option |idPlain| übergeben werden. Dann wird nach
% der exakten Übereinstimmung der hier notierten Identifikation mit dem Feld ID gesucht.
% Dies muss keine Zahl sein. Wird keine Option übergeben wird die notierte Zahl als
-% Zeilennummer startend bei 0 interpretiert. Außerdem kann man die Option |nophone|
-% übergeben, um das Telefonfeld auszublenden.
+% Zeilennummer startend bei 0 interpretiert.
%
% \DescribeMacro{\Anhang}\label{Anhang}
% An zwei Stellen in einer Bewerbung werden angehangene Dokumente ausgewiesen: Titelseite
@@ -671,7 +670,7 @@
% wird |classic| verwendet. Dieser Stil wurde leicht an den aus |komacv| angepasst. Außerdem
% wurden die Stile |casual| und |old-style| aus |komacv| ohne Bearbeitung importiert
% \autocite[vgl.][]{komacv}.
-% \item{|idPlain|} In der Datei |anschrift| müssen bereits die aktuellen Informationen zu
+% \item{|idPlain|} In der Datei |anschrift| müssen bereits die aktuellen Daten zu
% dieser Bewerbung vorliegen. Über den Befehl |\ID|\marg{Identifikation} kann die zu
% verwendende Bewerbung angegeben werden (vgl. \prettyref{sec:konfiguration}). Durch die
% Angabe der Option |idPlain| kann erzwungen werden, dass nach dem exakten Eintrag in
@@ -1275,10 +1274,10 @@
% name and title
% \begin{macrocode}
\begin{minipage}[b]{\@titlenamewidth}%
- \firstnamestyle{\firstname}\\[0.75em] %
% \end{macrocode}
%% ahilbig begin
% \begin{macrocode}
+ \firstnamestyle{\firstname}\\ %
\familynamestyle{\familyname}%
\ifdefempty{\acadtitle}{}{%
\\[1.25em]\acadtitlestyle{\acadtitle}}%
@@ -3022,7 +3021,7 @@
%
% \begin{macro}{\tel}
% \begin{macrocode}
-\providecommand{\tel}{empty}
+\providecommand{\tel}{}
% \end{macrocode}
% \end{macro}
%
@@ -3050,10 +3049,10 @@
% \begin{macrocode}
\ProvideDocumentCommand{\anhang}{o}{%
\IfNoValueTF{#1}{%
- \lebenslaufTitel.\anhangTmpFlat
+ Curriculum Vitae.\anhangTmpFlat
}{%
\item Anschreiben
- \item \lebenslaufTitel
+ \item Curriculum Vitae
\anhangTmpList
} %
}
@@ -3427,9 +3426,7 @@
\providecommand{\runKomaVar}{%
\setkomavar{fromname}{\fullname} %
\setkomavar{fromaddress}{\street\\\plz\xspace\stadt} %
- \ifthenelse{\equal{\tel}{empty}}{}{%
- \setkomavar{fromphone}[\Telefon\enskip]{\tel} %
- }%
+ \setkomavar{fromphone}[\Telefon\enskip]{\tel} %
\setkomavar{fromfax}[\Mobilefone\enskip]{\mobile} %
\setkomavar{fromemail}[\Letter\enskip]{\email} %
\setkomavar{signature}{\vorname\xspace\name} %
@@ -3450,9 +3447,7 @@
\renewcommand*{\addressstreet}{\street} %
\renewcommand*{\addresscity}{\plz\xspace\stadt} %
\renewcommand*{\address}{\street\\\plz\xspace\stadt} %
- \ifthenelse{\equal{\tel}{empty}}{}{%
- \renewcommand*{\phonenr}{\tel} %
- }%
+ \renewcommand*{\phonenr}{\tel} %
% \end{macrocode}
%\iffalse
%% \renewcommand*{\extrainfo}{Some extra info}
@@ -3509,10 +3504,7 @@
\ProvideDocumentEnvironment{lebenslauf}{oo}{%
\clearpage
\newgeometry{top=2.5cm,left=3cm,right=2.5cm,bottom=3cm}
- %\pagestyle{empty}
- \pagenumbering{arabic}
- \hypersetup{hidelinks}
- \ofoot{Seite \thepage\ von \pageref{LastPage}}
+ \pagestyle{empty}
\ifthenelse{\equal{#1}{none}}{\renewcommand{\@listitemsymbol}{}}{} %
%\iffalse
%%\clearscrheadfoot
@@ -3526,7 +3518,6 @@
\fullname\\
\todayOrt, \todayTime
\end{tabular}
- \label{LastPage}
\end{raggedright}
\IfNoValueF{#2}{%
\newpage %
@@ -3683,27 +3674,16 @@ setkeys=\kvsetkeys%
\DeclareStringOption[classic]{lebenslaufStyle}[classic]
\DeclareStringOption[anschrift.csv]{anschrift}[anschrift.csv]
\DeclareBoolOption{idPlain}
-\DeclareBoolOption{nophone}
\ProcessKeyvalOptions{ahbewerbung} % evaluate keyval options
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{scrlttr2}}
\ProcessOptions\relax
-\ifahbewerbung@nophone %
- \LoadClass[
- DIN, pagenumber=botright, backaddress=true, parskip=half,%
- fromalign=left, fromemail=true, fromfax=true, %
- fromphone=false, fromurl=false, fromalign=right, %
- fromlogo=false, fromrule=true, foldmarks=true, %
- paper=a4, fontsize=10pt,enlargefirstpage=true, firstfoot=false
- ]{scrlttr2}
-\else %
- \LoadClass[
- DIN, pagenumber=botright, backaddress=true, parskip=half,%
- fromalign=left, fromemail=true, fromfax=true, %
- fromphone=true, fromurl=false, fromalign=right, %
- fromlogo=false, fromrule=true, foldmarks=true, %
- paper=a4, fontsize=10pt,enlargefirstpage=true, firstfoot=false
- ]{scrlttr2}
-\fi %
+\LoadClass[
+ DIN, pagenumber=botright, backaddress=true, parskip=half,%
+ fromalign=left, fromemail=true, fromfax=true, %
+ fromphone=true, fromurl=false, fromalign=right, %
+ fromlogo=false, fromrule=true, foldmarks=true, %
+ paper=a4, fontsize=10pt,enlargefirstpage=true, firstfoot=false
+]{scrlttr2}
% \end{macrocode}
%\iffalse
%% import from komacv.cls for easier maintaining
@@ -3715,8 +3695,8 @@ setkeys=\kvsetkeys%
ifluatex,%
ifxetex,%
marvosym, %
- scrlayer-scrpage,%
- array,%
+ scrlayer-scrpage, %
+ array,%
graphicx,%
microtype,%
enumitem, %
@@ -3867,9 +3847,9 @@ cd ..
\textbf{\meinBeruf} \\ \ \\
\street\\
\plz\ \stadt\\
+ \Letter\enskip \email\\
\Telefon\enskip \tel\\
\Mobilefone\enskip \mobile
- \letter\enskip \email\\
\vfill
\textbf{Inhalt}
@@ -3886,10 +3866,8 @@ cd ..
\leftskip=0.3cm
\hspace*{0.1cm}\textit{bei}\\ % hier gehört bei rein
\textbf{\bewerbungFirma}\\
- \ifthenelse{\equal{\bewerbungFirmaName}{n}}{}{%
- \bewerbungFirmaAnrede\
- \bewerbungFirmaName\\
- }
+ \bewerbungFirmaAnrede\
+ \bewerbungFirmaName\\
\bewerbungFirmaStr\\
\bewerbungFirmaPlz\ \bewerbungFirmaOrt
% \end{macrocode}
diff --git a/macros/latex/contrib/bewerbung/bewerbung.ins b/macros/latex/contrib/bewerbung/bewerbung.ins
index 049fe18f90..a9754f3116 100644
--- a/macros/latex/contrib/bewerbung/bewerbung.ins
+++ b/macros/latex/contrib/bewerbung/bewerbung.ins
@@ -1,10 +1,10 @@
-% bewerbung.ins generated using makedtx version 0.94b 2020-11-24:11:30:14 -- Version 1.2/11/24 11:30
+% bewerbung.ins generated using makedtx version 0.94b 2022-01-17:16:26:37 -- Version 1.3/1/17 16:26
\input docstrip
\preamble
bewerbung.dtx
- Copyright 2020-11-24:11:30:14 -- Version 1.2 André Hilbig, mail@andrehilbig.de
+ Copyright 2022-01-17:16:26:37 -- Version 1.3 André Hilbig, mail@andrehilbig.de
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3
diff --git a/macros/latex/contrib/bewerbung/bewerbung.pdf b/macros/latex/contrib/bewerbung/bewerbung.pdf
index 6d8510b439..0580e5f15b 100644
--- a/macros/latex/contrib/bewerbung/bewerbung.pdf
+++ b/macros/latex/contrib/bewerbung/bewerbung.pdf
Binary files differ
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.bbx b/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.bbx
index f6f01c2118..14007cc66f 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.bbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.bbx
@@ -1,4 +1,4 @@
-\ProvidesFile{lncs.bbx}[2021/08/17 v0.3]
+\ProvidesFile{lncs.bbx}[2022/01/17 v0.4]
\RequireBibliographyStyle{numeric}
@@ -135,7 +135,7 @@
{\namepartsuffix}
\ifthenelse{\value{listcount}<\value{liststop}}
{\addcomma\space}%
- {}%
+ {\ifmorenames{\addcomma\nbspace\bibstring[\emph]{andothers}:}}%
}
\DeclareNameFormat{editor}{%
@@ -147,7 +147,7 @@
{\namepartsuffix}
\ifthenelse{\value{listcount}<\value{liststop}}
{\addcomma\space}%
- {\space\ifthenelse{\value{listcount}>1}
+ {\ifmorenames{\addcomma\nbspace\bibstring[\emph]{andothers}}\space\ifthenelse{\value{listcount}>1}
{(\bibstring{editors})}
{(\bibstring{editor})}}%
}
diff --git a/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.cbx b/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.cbx
index 40bb60d403..4b6c71ce61 100644
--- a/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.cbx
+++ b/macros/latex/contrib/biblatex-contrib/biblatex-lncs/lncs.cbx
@@ -1,4 +1,4 @@
-\ProvidesFile{lncs.cbx}[2021/08/17 v0.3]
+\ProvidesFile{lncs.cbx}[2022/01/17 v0.4]
\RequireCitationStyle{numeric}
diff --git a/macros/latex/contrib/dbshow/dbshow.dtx b/macros/latex/contrib/dbshow/dbshow.dtx
index a2af27d922..9731797f76 100644
--- a/macros/latex/contrib/dbshow/dbshow.dtx
+++ b/macros/latex/contrib/dbshow/dbshow.dtx
@@ -143,10 +143,10 @@ Copyright and License
\fi
%</internal>
%<package>\NeedsTeXFormat{LaTeX2e}
-%<+package|config>\GetIdInfo$Id: dbshow.dtx 461d9bb 2022-01-14 02:50:24 +0800 Changkai Li <lichangkai225@qq.com> $
+%<+package|config>\GetIdInfo$Id: dbshow.dtx 1a507c4 2022-01-17 22:53:24 +0800 Changkai Li <lichangkai225@qq.com> $
%<package> {Database to store and display data}
%<package>\ProvidesExplPackage{\ExplFileName}
-%<package|config> {\ExplFileDate}{1.4}{\ExplFileDescription}
+%<package|config> {\ExplFileDate}{1.5}{\ExplFileDescription}
%<*driver>
\documentclass[full]{l3doc}
\usepackage[scheme=plain, fontset=ubuntu]{ctex}
@@ -161,6 +161,9 @@ Copyright and License
\usepackage{xcolor}
\usepackage{tabularray}
\usepackage{zhnumber}
+\usepackage{tcolorbox}
+\tcbuselibrary{skins, minted, breakable, xparse}
+\usepackage{accsupp}
\geometry{
left=4.5cm,
@@ -197,8 +200,6 @@ Copyright and License
\addcontentsline{toc}{part}{Change~History}
}
-\let\subsubitem\subitem
-
\DoNotIndex{\begin, \end}
\setlength{\parskip}{\medskipamount}
@@ -217,6 +218,56 @@ Copyright and License
\par\textbf{\textsf{NOTE:~}}#1\par
} {}
+\definecolor {exambg} {RGB} {248, 241, 224} % 示例背景
+\definecolor {examno} {RGB} {176, 101, 90} % 示例行号
+\definecolor {examnobg} {RGB} {241, 225, 208} % 示例行号背景
+\definecolor {examframe} {RGB} {156, 129, 110} % 示例边框(标题背景)
+\definecolor {option} {HTML} {009933} % 选项
+\definecolor {cs} {HTML} {FF6600} % 命令
+\definecolor {env} {HTML} {C81531} % 环境
+\definecolor {link} {HTML} {33539E} % 链接
+
+% \definecolor {exambg} {RGB} {241, 225, 208} % 示例背景
+% \definecolor {examno} {HTML} {F3AA20} % 示例行号
+% \definecolor {examnobg} {HTML} {8B4C70} % 示例行号背景
+% \definecolor {examframe} {HTML} {58094F} % 示例边框(标题背景)
+% \definecolor {option} {HTML} {8B4C70} % 选项
+% \definecolor {cs} {HTML} {F3AA20} % 命令
+% \definecolor {cs} {HTML} {F9A911} % 命令
+% \definecolor {env} {HTML} {669933} % 环境
+\hypersetup{linkcolor=link}
+\tcbset{
+ exam-base/.style={
+ listing engine=minted, listing and text,
+ minted style=emacs, breakable,
+ minted options={fontsize=\small,breaklines,linenos,numbersep=3mm},
+ colback=exambg, colframe=examframe,
+ left=5mm, enhanced,
+ fonttitle=\small\sffamily\bfseries, fontlower=\small,
+ overlay={
+ \begin{tcbclipinterior}
+ \fill[examnobg]
+ (frame.south west) rectangle ([xshift=5mm]frame.north west);
+ \end{tcbclipinterior}
+ }
+ }
+}
+\DeclareTCBListing[auto counter]{example}{ O{} D(){} m }{%
+ exam-base, title={示例 \thetcbcounter:#3}, label={cn-#2}, #1
+}
+\DeclareTCBListing[auto counter]{example*}{ O{} D(){} m }{%
+ exam-base, title={Example \thetcbcounter: #3}, label={en-#2}, #1
+}
+\renewcommand{\theFancyVerbLine}{%
+ \ttfamily\textcolor{examno}{%
+ \scriptsize\oldstylenums{%
+ \protect\BeginAccSupp{ActualText={}}%
+ \arabic{FancyVerbLine}%
+ \protect\EndAccSupp{}%
+ }%
+ }%
+}
+
\ExplSyntaxOn
\makeatletter
@@ -274,7 +325,7 @@ Copyright and License
\int_compare:nNnT { \str_count:n {#1} } = { 3 } { \phantom{0} }
\c_space_tl
}
-\cs_set_eq:NN \dbshowdocver \dbshowdoc_print_version:n
+\cs_gset_eq:NN \dbshowdocver \dbshowdoc_print_version:n
% #1 ver #2 date #3 type #4 desc
\cs_new_protected:Nn \dbshowdoc_changes_what:nnnn {
@@ -336,13 +387,26 @@ Copyright and License
\end{itemize}
} {}
-\cs_new_protected:Nn \dbshowdoc_function_begin:N {
+\cs_gset_protected:Npn \__codedoc_typeset_function_block:nN #1#2 {
+ \__codedoc_function_index:x
+ { #1 \bool_if:NT #2 { \tl_to_str:n {TF} } }
+ \__codedoc_function_label:xN {#1} #2
+ \color{cs}\bfseries #1
+ \bool_if:NT #2 { \__codedoc_typeset_TF: }
+ \__codedoc_typeset_expandability:
+ \seq_if_empty:NF \g__codedoc_variants_seq
+ { \__codedoc_typeset_variant_list:nN {#1} #2 }
+ \\
+}
+\cs_new_protected:Nn \dbshowdoc_function_begin:Nn {
\cs_set_eq:NN \__codedoc_tmp_cs:nN \__codedoc_typeset_function_block:nN
\cs_set_protected:Npn \__codedoc_typeset_function_block:nN ##1##2 {
\__codedoc_function_label:xN {##1} ##2
\hbox_set:Nn \l_tmpa_box {##1}
- \int_compare:nTF { \str_count:n {##1} <= 22 }
+ \group_begin: \color{#2}\bfseries
+ \int_compare:nTF { \str_count:n {##1} <= 20 }
{##1} { \adjustbox{width=.7\marginparwidth, height=\box_ht:N \l_tmpa_box}{##1} }
+ \group_end:
#1{##1}
\__codedoc_typeset_expandability: \\
}
@@ -352,7 +416,7 @@ Copyright and License
}
\DeclareDocumentEnvironment { option } { O{} +v }
{
- \dbshowdoc_function_begin:N \SpecialOptionIndex
+ \dbshowdoc_function_begin:Nn \SpecialOptionIndex { option }
\__codedoc_function:nnw {#1} {#2}
}
{
@@ -361,7 +425,7 @@ Copyright and License
}
\DeclareDocumentEnvironment { environment } { O{} +v }
{
- \dbshowdoc_function_begin:N \SpecialEnvIndex
+ \dbshowdoc_function_begin:Nn \SpecialEnvIndex { env }
\__codedoc_function:nnw {#1} {#2}
}
{
@@ -369,8 +433,81 @@ Copyright and License
\dbshowdoc_function_end:
}
+\makeatletter
+\cs_gset_protected:Npn \__codedoc_cmd:nn #1#2
+ {
+ \bool_set_false:N \l__codedoc_cmd_noindex_bool
+ \bool_set_true:N \l__codedoc_cmd_replace_bool
+ \tl_set:Nn \l__codedoc_cmd_index_tl { \q_no_value }
+ \tl_set:Nn \l__codedoc_cmd_module_tl { \q_no_value }
+ \keys_set:nn { l3doc/cmd } {#1}
+ \tl_set:Nn \l__codedoc_cmd_tl {#2}
+ \bool_if:NT \l__codedoc_cmd_replace_bool
+ {
+ \tl_set_rescan:Nnn \l__codedoc_tmpb_tl { } { _ }
+ \tl_replace_all:Non \l__codedoc_cmd_tl \l__codedoc_tmpb_tl { _ }
+ \__codedoc_replace_at_at:N \l__codedoc_cmd_tl
+ \tl_replace_all:Nno \l__codedoc_cmd_tl { _ } \l__codedoc_tmpb_tl
+ }
+ \mode_if_math:T { \mbox }
+ {
+ \bool_if:NT \l__codedoc_allow_indexing_bool { \__codedoc_target: }
+ \verbatim@font
+ \__codedoc_if_almost_str:VT \l__codedoc_cmd_tl
+ {
+ \__kernel_tl_set:Nx \l__codedoc_cmd_tl { \tl_to_str:N \l__codedoc_cmd_tl }
+ \bool_if:NT \g__codedoc_cs_break_bool
+ {
+ \regex_replace_all:nnN
+ { ([^\\\_]\_*) \_ ([^\_]) }
+ { \1 \c{BreakableUnderscore} \2 }
+ \l__codedoc_cmd_tl
+ }
+ }
+ \tl_replace_all:Nnn \l__codedoc_cmd_tl { ~ } { \@xobeysp }
+ \textbf{\l__codedoc_cmd_tl}
+ \@
+ }
+ \bool_if:NT \l__codedoc_allow_indexing_bool
+ {
+ \bool_if:NF \l__codedoc_cmd_noindex_bool
+ {
+ \quark_if_no_value:NF \l__codedoc_cmd_index_tl
+ {
+ \__kernel_tl_set:Nx \l__codedoc_cmd_tl
+ { \c_backslash_str \exp_not:o { \l__codedoc_cmd_index_tl } }
+ }
+ \exp_args:No \__codedoc_key_get:n { \l__codedoc_cmd_tl }
+ \quark_if_no_value:NF \l__codedoc_cmd_module_tl
+ {
+ \__kernel_tl_set:Nx \l__codedoc_index_module_tl
+ { \tl_to_str:N \l__codedoc_cmd_module_tl }
+ }
+ \__codedoc_special_index_module:ooonN
+ { \l__codedoc_index_key_tl }
+ { \l__codedoc_index_macro_tl }
+ { \l__codedoc_index_module_tl }
+ { usage }
+ \l__codedoc_index_internal_bool
+ }
+ }
+ }
+\cs_generate_variant:Nn \__codedoc_cmd:nn { no }
+\makeatother
+
+% #1 color #2 opt #3 content
+\cs_new_protected:Nn \dbshowdoc_cmd:nnn {
+ \__codedoc_get_hyper_target:xN {#3} \l_tmpa_tl
+ \hyperref[\l_tmpa_tl]{\textcolor{#1}{\__codedoc_cmd:no {#2} {#3}}}
+}
\DeclareDocumentCommand \opt { O{} m }
- { \__codedoc_cmd:no {#1} {#2} }
+ { \dbshowdoc_cmd:nnn { option } {#1} {#2} }
+\DeclareDocumentCommand \nopt { O{} m }
+ { \textcolor{option}{\textbf{#2}} }
+\DeclareDocumentCommand \env { O{} m }
+ { \dbshowdoc_cmd:nnn { env } {#1} {#2} }
+\DeclareDocumentCommand \cs { O{} m }
+ { \dbshowdoc_cmd:nnn { cs } {#1} { \c_backslash_str #2 } }
\NewDocumentCommand \linktarget { m m m } {%
\hyperlink{#1}{#3}%
@@ -385,6 +522,19 @@ Copyright and License
{ \GetIdInfo $Id$ }
{ \fileinfo }
}
+
+\DeclareDocumentCommand \inidef { s d() s o } {
+ \group_begin:
+ \hfill\normalfont(
+ initially~
+ \IfBooleanTF {#1} {empty}
+ { \IfValueTF {#2} { \texttt{#2} } { unset } }
+ ,~
+ \IfBooleanTF {#3} {default empty}
+ { \IfValueTF {#4} { default~\texttt{#4} } { no~default } }
+ )
+ \group_end:
+}
\ExplSyntaxOff
\begin{document}
@@ -402,7 +552,7 @@ Copyright and License
%</driver>
% \fi
%
-% \CheckSum{882}
+% \CheckSum{0}
% \GetFileId{dbshow.sty}
%
% \ExplSyntaxOn
@@ -428,15 +578,11 @@ Copyright and License
% \begin{documentation}
%
% \section{引言}
+%
% 编写本宏包的动机来源于当前没有一个很好的错题本宏包,可以方便的根据各种条件对错
% 题进行筛选、排序,然后以自定义的样式展示出来。\pkg{dbshow} 宏包实现了四个核心
% 功能:数据存储和使用、数据筛选、数据排序、数据展示。
%
-% 数据只需要存储一次,就可以通过预定义的筛选、排序条件和样式展示部分或全部的数据。
-% 如上所述,本宏包其实实现了一个非常简单的数据库,复习错题的功能只是其中一个应用,
-% 和其他数据库宏包比如 \pkg{datatool} 相比,\pkg{dbshow} 更专注于非图表类型的数
-% 据展示。
-%
% \changes{1.4}{2022-01-10}{Add check}{version of \pkg{l3kernel}}
% \pkg{dbshow} 依赖版本日期至少为 |2022-11-07| 的 \pkg{l3kernel}。
%
@@ -473,19 +619,8 @@ Copyright and License
% 除了日期类型,所有类型都是 \pkg{expl3} 的内置类型。\pkg{dbshow} 构建了一个简单
% 的 |date| 类型,支持转换成整数以及带样式的打印。
%
-% \subsection{与 \pkg{datatool} 的区别}
-%
% \changes{1.2}{2022-01-07}{Add doc}{add comparison to \pkg{datatool}}
-%
-% 从核心功能上看,\pkg{dbshow} 和 \pkg{datatool} 实现了相同的功能。区别在于
-% \pkg{dbshow} 基于 \pkg{expl3} 实现,支持字符串的正则匹配,还支持多级排序。使用
-% 方式上更倾向于样式与内容分离,所有的样式都可以通过选项提前定义好并且可以复用。
-% \pkg{dbshow} 并没有实现从外部文件读取数据以及将数据持久化的功能,我认为这些应
-% 该是更专业的外部程序的工作而不应该在 \LaTeX 中设计这些功能。因此,\pkg{dbshow}
-% 只提供了一个运行时的临时数据库,足够轻便且满足大部分正常需求。如果你想删除或修
-% 改数据库中某一条记录,请去对应的位置删除或修改掉对应的 \env{dbitem} 环境,而不
-% 是让宏包提供一个输出某一行记录的命令。某种意义上记录数据库的 \TeX 源文件本身就
-% 是数据的一种持久化。
+% \changes{1.3}{2022-01-07}{Remove doc}{remove comparison to \pkg{datatool}}
%
% \section{接口文档}
%
@@ -531,18 +666,6 @@ Copyright and License
% 每个数据库都有一个默认的属性 |id| 用来存储数据的索引。
% \end{note}
%
-% 下面是定义一个错题数据库的示例,|question| 和 |answer| 属性用来存储问题和答
-% 案,|date| 属性存储日期,|info| 属性存储额外信息,|labels| 存储题目标签。
-% \begin{verbatim}
-% \dbNewDatabase{ques}{
-% question = tl,
-% answer = tl,
-% date = date,
-% info = tl,
-% labels = clist
-% }
-% \end{verbatim}
-%
% \begin{function}[added=2022-01-05]{\dbshow}
% \begin{syntax}
% \cs{dbshow} \marg{style} \marg{database}
@@ -561,7 +684,7 @@ Copyright and License
%
% \subsection{\cs{dbNewStyle} 和样式选项}
%
-% \begin{function}[added=2022-01-05]{\dbNewStyle}
+% \begin{function}[added=2022-01-05, updated=2022-01-15]{\dbNewStyle}
% \begin{syntax}
% \cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts}
% \end{syntax}
@@ -574,222 +697,343 @@ Copyright and License
%
% \begin{option}[added=2022-01-05]{filter}
% \begin{syntax}
-% filter = <filter>
+% \opt{filter} = <filter> \inidef(-none-)
% \end{syntax}
%
-% 为当前样式设置由 \cs{dbCombineFilters} 所定义的过滤器
+% 为当前样式设置由 \cs{dbCombineFilters} 所定义的过滤器。示例 \ref{cn-filter}
+% 演示了如何定义条件,将条件组合成过滤器以及使用过滤器。
% \end{option}
%
+% \iffalse
+%<*verb>
+% \fi
+\DeleteShortVerb{\|}
+\begin{example}(filter){使用过滤器筛选数据}
+ \dbNewDatabase{filter-db}{name=str, count=int}
+ \begin{dbFilters}{filter-db}
+ \dbNewCond {cond1}{count}{\dbval > 3}
+ \dbNewCond*{cond2}{name} {\d+}
+ \dbCombCond{filter-and}{cond1 && cond2}
+ \dbCombCond{filter-or} {cond1 || cond2}
+ \end{dbFilters}
+ \dbitemkv{filter-db}{name=123, count=4}
+ \dbitemkv{filter-db}{name=ab3, count=2}
+ \dbitemkv{filter-db}{name=bag, count=5}
+ \dbNewStyle{filter-and-style}{filter-db}{
+ filter = filter-and,
+ before-code = \par Filter And\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbNewStyle{filter-or-style}{filter-db}{
+ filter = filter-or,
+ before-code = \par Filter Or\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbshow{filter-and-style}{filter-db}
+ \dbshow{filter-or-style} {filter-db}
+\end{example}
+\MakeShortVerb{\|}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}}
% \begin{option}[added=2022-01-06]{raw-filter}
% \begin{syntax}
-% raw-filter = <conditional expression>
+% \opt{raw-filter} = <conditional expression> \inidef
% \end{syntax}
%
% 使用条件表达式设置匿名过滤器,这里的条件指通过 \cs{dbNewConditional} 定义的
-% 条件。下面代码中两个示例的过滤器具有相同的功能。
+% 条件。示例 \ref{cn-raw-filter} 使用 \opt{raw-filter} 选项,直接组合筛选条
+% 件,达到与示例 \ref{cn-filter} 相同的效果。
% \end{option}
%
-% \changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}}
-%
-% \begin{verbatim}
-% % method 1
-% \begin{dbFilters}{db}
-% \dbNewConditional{cond1}{int-attr}{\rval > 1}
-% \dbNewConditional*{cond2}{str-attr}{\d+}
-% \end{dbFilters}
-% \dbNewStyle{style}{db}{raw-filter={cond1 && cond2}}
-% % method 2
-% \begin{dbFilters}{db}
-% \dbNewConditional{cond1}{int-attr}{\rval > 1}
-% \dbNewConditional*{cond2}{str-attr}{\d+}
-% \dbCombineFilters{filter}{cond1 && cond2}
-% \end{dbFilters}
-% \dbNewStyle{style}{db}{filter=filter}
-% \end{verbatim}
+% \DeleteShortVerb{\|}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(raw-filter){使用匿名过滤器筛选数据}
+ \dbNewDatabase{filter-db}{name=str, count=int}
+ \begin{dbFilters}{filter-db}
+ \dbNewCond {cond1}{count}{\dbval > 3}
+ \dbNewCond*{cond2}{name} {\d+}
+ \end{dbFilters}
+ \dbitemkv{filter-db}{name=123, count=4}
+ \dbitemkv{filter-db}{name=ab3, count=2}
+ \dbitemkv{filter-db}{name=bag, count=5}
+ \dbNewStyle{filter-and-style}{filter-db}{
+ raw-filter = {cond1 && cond2},
+ before-code = \par Filter And\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbNewStyle{filter-or-style}{filter-db}{
+ raw-filter = {cond1 || cond2},
+ before-code = \par Filter Or\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbshow{filter-and-style}{filter-db}
+ \dbshow{filter-or-style} {filter-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+% \MakeShortVerb{\|}
%
% \changes{1.2}{2022-01-08}{Fix bug}{string sorting bug}
% \begin{option}[added=2022-01-05]{sort}
% \begin{syntax}
-% sort = \{ <attr spec1>, <attr spec2>, \ldots{} \}
+% \opt{sort} = \{ <attr spec1>, <attr spec2>, \ldots{} \} \inidef
% \end{syntax}
%
-% 为当前样式设置排序规则。支持根据 |str|,|date|,|int|,|fp| 类型的数据进行排
-% 序,支持多级排序。\meta{attr} 表示增序,\meta{attr}* 表示降序。下面例子中,
-% 使用 |sort-style| 展示数据时的顺序为先按 |level| 降序,|level| 相同的再按出
-% 生日期 |birth| 增序,以此类推。
+% 为当前样式设置排序规则。支持对 |str|,|date|,|int|,|fp| 类型的数据进行排
+% 序,支持多级排序。\meta{attr} 表示增序,\meta{attr}\texttt{*} 表示降序。示
+% 例 \ref{cn-sort} 的排序规则为先按 |count| 降序排序,|count| 相同的再按
+% |name| 增序排序。
% \end{option}
%
-% \begin{verbatim}
-% \dbNewDatabase{sort-example}{
-% name = str,
-% birth = date,
-% level = int,
-% weight = fp,
-% }
-% \dbNewStyle{sort-style}{sort-example}{
-% sort = { level*, birth, name, weight }
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(sort){多级排序}
+ \dbNewDatabase{sort-db}{name=str, count=int}
+ \dbNewStyle{sort-style}{sort-db}{
+ sort = {count*, name},
+ item-code = {\dbuse{name}: \dbuse{count}\quad}
+ }
+ \dbitemkv{sort-db}{name=bag, count=1}
+ \dbitemkv{sort-db}{name=box, count=1}
+ \dbitemkv{sort-db}{name=tag, count=2}
+ \dbitemkv{sort-db}{name=pen, count=3}
+ \dbshow{sort-style}{sort-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
%
-% \begin{option}[added=2022-01-05, rEXP]{item-code}
+% \begin{option}[added=2022-01-05, rEXP]{before-code}
% \begin{syntax}
-% item-code = <code>
+% \opt{before-code} = <before code> \inidef*
% \end{syntax}
%
-% 该选项用来设置展示数据库中每条记录的代码。你可以使用 \cs{dbuse} 来展示属性的
-% 值。
+% 该选项用来设置在展示整个数据库之\zhbefore 需要执行的代码(见示例
+% \ref{cn-db-wrap})。
% \end{option}
%
-% \changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}}
-% \begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep}
+% \begin{option}[added=2022-01-05, rEXP]{after-code}
% \begin{syntax}
-% <attr>/sep = <separator> \\
-% <attr>/sep = \{ \\
-% ~~\meta{separator between two}, \\
-% ~~\meta{separator between more than two}, \\
-% ~~\meta{separator between final two} \\
-% \} \\
-% <attr>/sep = \{ \\
-% ~~\meta{separator before year}, \\
-% ~~\meta{separator between year and month}, \\
-% ~~\meta{separator between month and day}, \\
-% ~~\meta{separator after day} \\
-% \} \\
+% \opt{after-code} = <after code> \inidef*
% \end{syntax}
%
-% 该选项只适用于类型为 |clist| 或 |date| 的属性,用来设置列表间元素的间隔。参
-% 数为一个 \meta{separator} 时,所有元素间的分隔符被设置为 \meta{separator}。
-% \meta{separator before year} 和 \meta{separator after day} 被设置为空。
+% 该选项用来设置在展示整个数据库之\zhafter 需要执行的代码(见示例
+% \ref{cn-db-wrap})。
% \end{option}
%
-% 参数为3个元素的逗号分隔的列表时,此选项用来设置列表元素的分隔符,分别用来设
-% 置只有两个元素时的分隔符 \meta{separator between two},超过两个元素时的分隔
-% 符 \meta{separator between more than two},和最后两个元素之间的分隔符
-% \meta{separator between final two}。对于类型为 |clist| 的属性,设置此选项时
-% 如果参数列表数量不是1或者3会触发报错。
-%
-% \begin{verbatim}
-% % clist-attr is an attribute of database db
-% % suppose the val of clist-attr is { 1, 2, 3 }
-% \dbNewStyle{clist-sep}{db}{
-% clist-attr/sep = { ,~ }, % print 1, 2, 3
-% clist-attr/sep = { {,~}, {,~}, {and~} } % print 1, 2 and 3
-% }
-% \end{verbatim}
-%
-% 参数为4个元素的逗号分隔的列表时,此选项用来设置日期的分隔符,分别用来设
-% 置 \meta{year} 之前的分隔符 \meta{separator before year} ,\meta{year} 和
-% \meta{month} 之间的分隔符 \meta{separator between year and month} ,
-% \meta{month} 和 \meta{day} 之间的分隔符,以及 \meta{day} 之后的分隔符。对于
-% 类型为 |date| 的属性,设置此选项时如果参数列表数量不是1或者4会触发报错。
-%
-% \begin{verbatim}
-% % date-attr is an attribute of database db
-% % suppose the val of date-attr is 2022/01/01
-% \dbNewStyle{date-sep}{db}{
-% date-attr/sep = -, % print 2022-01-01
-% date-attr/sep = { |, -, -, | } % print |2022-01-01|
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(db-wrap){设置展示数据库前后的代码}
+ \dbNewDatabase{wrap-db}{text=tl}
+ \dbNewStyle{wrap-style}{wrap-db}{
+ before-code = \textit{before code}\quad,
+ after-code = \textit{after code},
+ item-code = \dbarabic.~\dbuse{text}\quad
+ }
+ \dbitemkv{wrap-db}{text=text1}
+ \dbitemkv{wrap-db}{text=text2}
+ \dbitemkv{wrap-db}{text=text3}
+ \dbshow{wrap-style}{wrap-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
%
-% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}}
-% \begin{option}[added=2022-01-08, EXP]{<attr>/zfill}
+% \begin{option}[added=2022-01-05, rEXP]{item-code}
% \begin{syntax}
-% <attr>/zfill = <\TTF>
+% \opt{item-code} = <item code> \inidef
% \end{syntax}
%
-% 该选项只适用于类型为 |date| 的属性。控制输出月份和天时是否补零。
+% 该选项用来设置展示数据库中每条记录的代码。你可以使用 \cs{dbuse}\marg{attr}
+% 来指代属性 \meta{attr} 的值。示例 \ref{cn-item-code} 演示了如何展示一个首
+% 字母缩写词表。
% \end{option}
%
-% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbdatesep}}
-% \begin{function}[added=2022-01-13, EXP]{\dbdatesep}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(item-code){展示数据库条目}
+ \dbNewDatabase{item-db}{acronym=str, desc=tl}
+ \dbNewStyle{item-style}{item-db}{
+ before-code = {\dbIfEmptyF{\begin{description}}},
+ after-code = {\dbIfEmptyF{\end{description}}},
+ item-code = {\item[\dbuse{acronym}] \dbuse{desc}},
+ sort = acronym,
+ }
+ \dbitemkv{item-db}{acronym=PM, desc={Prime Minister}}
+ \dbitemkv{item-db}{acronym=CBD, desc={Central Business District}}
+ \dbitemkv{item-db}{acronym=DL, desc={Deep Learning}}
+ \dbshow{item-style}{item-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-17}{Add option}{\opt{item-code*}}
+% \begin{option}[added=2022-01-17, rEXP]{item-code*}
% \begin{syntax}
-% \cs{dbdatesep} \marg{separator}
+% \opt{item-code*} = <item code> \inidef
% \end{syntax}
%
-% 设置内部解析日期时的间隔符,默认为 |/|,即存储数据的格式为 |yyyy/mm/dd|。
-% \end{function}
+% 使用该选项设置的代码在被插入到最终执行代码序列之前会先通过
+% \cs{protected@edef} 完全展开。示例 \ref{cn-item-exp} 展示了如何通过该选项
+% 使用表格来展示数据。
+% \end{option}
%
-% \subsubsection{装饰器}
-%
-% 下面这些选项在不同层次上装饰原有的展示代码,有些其实不必通过选项的形式来装饰,
-% 但这样做的好处是可以进一步使样式与内容分离。下面的例子中,\meta{style1} 和
-% \meta{style2} 是相同的样式,都用 * 将 \meta{attr1} 包裹住了,但是如果你还想定
-% 义一个样式用 = 将 \meta{attr1} 包裹住,如果用 \meta{style1} 的方式,那就可能
-% 需要重复大片代码,用 \meta{style2} 的方式则可以很轻松的继承 \meta{style1} 中的
-% 代码。
-%
-% \begin{verbatim}
-% \dbNewStyle{style1}{db}{
-% item-code = {%
-% *\rvuse{attr1}*\rvuse{attr2}
-% % more code
-% }
-% }
-% \dbNewStyle{base-style}{db}{
-% item-code = {%
-% \rvuse{attr1}\rvuse{attr2}
-% % more code
-% }
-% }
-% \dbNewStyle[base-style]{style2}{db}{
-% attr1/before-code = { * },
-% attr1/after-code = { * },
-% }
-% \dbNewStyle[base-style]{style3}{db}{
-% attr1/before-code = { = },
-% attr1/after-code = { = },
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example}(item-exp){用表格展示数据}
+ \dbNewDatabase{tab-db}{name=str, count=int}
+ \dbNewStyle{tab-style}{tab-db}{
+ before-code = {%
+ \begin{tabular}{ll}
+ name & count \\
+ },
+ after-code = \end{tabular},
+ item-code* = {%
+ \textcolor{red}{\dbuse{name}} & \dbuse{count} \\
+ },
+ }
+ \dbitemkv{tab-db}{name=bag, count=100}
+ \dbitemkv{tab-db}{name=pig, count=20}
+ \dbshow{tab-style}{tab-db}
+\end{example}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
%
-% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}}
-% \begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper}
+% \changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code},
+% \opt{record-after-code}}
+% \changes{1.5}{2022-01-14}{Update options}{Rename \opt{record-before-code}
+% and \opt{record-after-code} to \opt{item-before-code} and
+% \opt{item-after-code}}
+% \begin{option}[added=2022-01-08, updated=2022-01-14, rEXP]{item-before-code}
% \begin{syntax}
-% <attr>/wrapper = <control sequence>
+% \opt{item-before-code} = <before code> \inidef*
% \end{syntax}
%
-% 该选项只适用于类型为 |date| 的属性。\meta{control sequence} 只接收一个参数即
-% 日期,如果设置了此选项,则最后输出的日期为
-% \meta{control sequence}\marg{date}。
+% 在 \meta{item code} 之\zhbefore 执行的代码(见示例 \ref{cn-item-wrapper})。
% \end{option}
%
-% \begin{option}[added=2022-01-05, rEXP]{before-code}
+% \begin{option}[added=2022-01-08, updated=2022-01-14, rEXP]{item-after-code}
% \begin{syntax}
-% before-code = <code>
+% \opt{item-after-code} = <after code> \inidef*
% \end{syntax}
%
-% 该选项用来设置在展示整个数据库之\zhbefore 需要执行的代码。
+% 在 \meta{item code} 之\zhafter 执行的代码(见示例 \ref{cn-item-wrapper})。
% \end{option}
%
-% \begin{option}[added=2022-01-05, rEXP]{after-code}
-% \begin{syntax}
-% after-code = <code>
-% \end{syntax}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(item-wrapper){设置展示条目之前和之后的代码}
+ \dbNewDatabase{item-wrap-db}{text=tl, hint=tl}
+ \dbNewStyle{item-wrap-style}{item-wrap-db}{
+ item-before-code = \begingroup\ttfamily<,
+ item-after-code = >\endgroup,
+ item-code = \dbuse{text}~(\dbuse{hint}),
+ }
+ \dbitemkv{item-wrap-db}{text=example, hint={this is an example}}
+ \dbshow{item-wrap-style}{item-wrap-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
%
-% 该选项用来设置在展示整个数据库之\zhafter 需要执行的代码。
-% \end{option}
+% \subsubsection{属性选项}
%
-% \changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code},
-% \opt{record-after-code}}
-% \begin{option}[added=2022-01-05, rEXP]{record-before-code}
+% \changes{1.5}{2022-01-14}{Remove option}{\opt{<attr>/wrapper}}
+%
+% \changes{1.5}{2022-01-14}{Add options}{\opt{<attr>/code},
+% \opt{<attr>/code*}}
+% \begin{option}[added=2022-01-14, rEXP]{<attr>/code}
% \begin{syntax}
-% record-before-code = <code>
+% \nopt{<attr>/code} = <code> \inidef(\#1)
% \end{syntax}
%
-% 该选项用来设置在展示当前记录之\zhbefore 需要执行的代码。
+% 设置 \meta{attr} 的样式代码。在 \meta{code} 中用 |#1| 指代属性的值。示例
+% \ref{cn-attr-code} 将数量超过10个的物品打印为红色,少于10个的则打印为青色。
% \end{option}
%
-% \begin{option}[added=2022-01-05, rEXP]{record-after-code}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(attr-code){设置单个属性样式}
+ \dbNewDatabase{attr-code-db}{name=str, count=int}
+ \begin{dbFilters}{attr-code-db}
+ \dbNewCond{large}{count}{\dbval >= 10}
+ \end{dbFilters}
+ \dbNewStyle{base-style}{attr-code-db}{
+ item-code = \dbuse{name}:~\dbuse{count}\quad,
+ }
+ \dbNewStyle[base-style]{large-style}{attr-code-db}{
+ raw-filter = large,
+ name/code = \textcolor{red}{#1},
+ }
+ \dbNewStyle[base-style]{small-style}{attr-code-db}{
+ raw-filter = !large,
+ name/code = \textcolor{teal}{#1},
+ }
+ \dbitemkv{attr-code-db}{name=bag, count=1}
+ \dbitemkv{attr-code-db}{name=pen, count=12}
+ \dbitemkv{attr-code-db}{name=pig, count=5}
+ \dbitemkv{attr-code-db}{name=egg, count=50}
+ \dbshow{large-style}{attr-code-db}
+ \dbshow{small-style}{attr-code-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \begin{option}[added=2022-01-14, rEXP]{<attr>/code*}
% \begin{syntax}
-% record-after-code = <code>
+% \nopt{<attr>/code*} = <code> \inidef
% \end{syntax}
%
-% 该选项用来设置在展示当前记录之\zhafter 需要执行的代码。
+% 设置 \meta{attr} 的样式代码。在 \meta{code} 中用 |#1| 指代\textbf{展开}的
+% 属性的值。这对某些需要以特定格式解析参数的命令比较有用。
% \end{option}
%
+% 示例 \ref{cn-exp-code} 中 \pkg{zhnumber} 宏包的 \cs{zhdate} 命令接收
+% |yyyy/mm/dd| 格式的时期并输出中文日期,本宏包默认的日期输出格式是
+% |yyyy/mm/dd|,因此可以通过 \opt{date/code*} 选项,将日期完全展开后然后传递
+% 给 \cs{zhdate} 命令,如果不展开,\cs{zhdate} 接收到的是若干个用来展示日期
+% 的控制序列,而不是 |yyyy/mm/dd| 格式的时期,进而触发报错。
+%
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example}(exp-code){中文日期}
+ % \usepackage{zhnumber}
+ \dbNewDatabase{exp-db}{date=date, event=tl}
+ \dbNewStyle{exp-style}{exp-db}{
+ item-code = \par\makebox[4cm][l]{\dbuse{date}}\dbuse{event},
+ date/code* = \zhdate{#1},
+ }
+ \dbitemkv{exp-db}{date=2020/12/31, event=eat}
+ \dbitemkv{exp-db}{date=2021/01/01, event=sleep}
+ \dbshow{exp-style}{exp-db}
+\end{example}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
+%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/before-code}
% \begin{syntax}
-% <attr>/before-code = <code>
+% \nopt{<attr>/before-code} = <before code> \inidef*
% \end{syntax}
%
% 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhbefore 需要执行的代
@@ -798,16 +1042,60 @@ Copyright and License
%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/after-code}
% \begin{syntax}
-% <attr>/after-code = <code>
+% \nopt{<attr>/after-code} = <after code> \inidef*
% \end{syntax}
%
% 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhafter 需要执行的代码。
% \cs{dbuse} 会在展示属性数据\zhafter 执行此代码。
% \end{option}
%
+% 属性样式代码的执行顺序为:
+% \begin{enumerate}[nolistsep]
+% \item \opt{<attr>/before-code}
+% \item \opt{<attr>/code} or \opt{<attr>/code*}
+% \item \opt{<attr>/after-code}
+% \end{enumerate}
+%
+% \changes{1.5}{2022-01-16}{Add options}{\opt{<attr>/item-code},
+% \opt{<attr>/item-code*}}
+% \begin{option}[added=2022-01-16, rEXP]{<attr>/item-code}
+% \begin{syntax}
+% \nopt{<attr>/item-code} = <item code> \inidef(\#1)
+% \end{syntax}
+%
+% 设置列表元素的样式代码。在 \meta{item code} 中用 |#1| 指代列表元素的值。示例
+% \ref{cn-clist-code} 演示了如何为列表元素设置额外的样式。
+% \end{option}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(clist-code){设置列表元素样式代码}
+ \dbNewDatabase{clist-db}{name=str, label=clist}
+ \dbNewStyle{clist-style}{clist-db}{
+ item-code = \par\dbuse{name}:~\dbuse{label},
+ label/item-code = (\textcolor{red}{\textit{#1}}),
+ }
+ \dbitemkv{clist-db}{name=pig, label={animal, meat}}
+ \dbitemkv{clist-db}{name=Alex, label={person, male}}
+ \dbshow{clist-style}{clist-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \begin{option}[added=2022-01-16, rEXP]{<attr>/item-code*}
+% \begin{syntax}
+% \nopt{<attr>/item-code*} = <item code> \inidef
+% \end{syntax}
+%
+% 设置列表元素的样式代码。在 \meta{item code} 中用 |#1| 指代\textbf{展开}的列
+% 表元素的值。
+% \end{option}
+%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code}
% \begin{syntax}
-% <attr>/item-before-code = <code>
+% \nopt{<attr>/item-before-code} = <code> \inidef*
% \end{syntax}
%
% 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhbefore 需要
@@ -816,65 +1104,291 @@ Copyright and License
%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code}
% \begin{syntax}
-% <attr>/item-after-code = <code>
+% \nopt{<attr>/item-after-code} = <code> \inidef*
% \end{syntax}
%
% 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhafter 需要执
% 行的代码。
% \end{option}
%
-% \subsection{使用 \cs{dbNewReviewPoints} 定义复习点}
+% 列表元素样式代码的执行顺序为:
+% \begin{enumerate}[nolistsep]
+% \item \opt{<attr>/item-before-code}
+% \item \opt{<attr>/item-code} or \opt{<attr>/item-code*}
+% \item \opt{<attr>/item-after-code}
+% \end{enumerate}
+%
+% \def\sepini{%
+% \begingroup\normalfont%
+% \hfill%
+% (initially \texttt{\{,\char`~\}} for \texttt{clist}%
+% and \texttt{/} for \texttt{date}, no default)%
+% \endgroup%
+% }
+% \changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}}
+% \begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep}
+% \begin{syntax}
+% \nopt{<attr>/sep} = <separator> \sepini\\
+% \nopt{<attr>/sep} = \{ \\
+% ~~\meta{separator between two}, \\
+% ~~\meta{separator between more than two}, \\
+% ~~\meta{separator between final two} \\
+% \} \\
+% \nopt{<attr>/sep} = \{ \\
+% ~~\meta{separator before year}, \\
+% ~~\meta{separator between year and month}, \\
+% ~~\meta{separator between month and day}, \\
+% ~~\meta{separator after day} \\
+% \} \\
+% \end{syntax}
+%
+% 该选项只适用于类型为 |clist| 或 |date| 的属性,用来设置列表间元素的间隔。参
+% 数为一个 \meta{separator} 时,所有元素间的分隔符被设置为 \meta{separator}。
+% \meta{separator before year} 和 \meta{separator after day} 被设置为空。
+% \end{option}
+%
+% 参数为3个元素的逗号分隔的列表时,此选项用来设置列表元素的分隔符,分别用来设
+% 置只有两个元素时的分隔符 \meta{separator between two},超过两个元素时的分隔
+% 符 \meta{separator between more than two},和最后两个元素之间的分隔符
+% \meta{separator between final two}。对于类型为 |clist| 的属性,设置此选项时
+% 如果参数列表数量不是1或者3会触发报错。示例 \ref{cn-clist-sep} 展示了如何设
+% 置列表元素间隔。
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(clist-sep){设置列表元素间隔}
+ \dbNewDatabase{clist-db}{label=clist}
+ \dbNewStyle{clist-base}{clist-db}{
+ before-code = {\dbIfEmptyF{\begin{enumerate}}},
+ after-code = {\dbIfEmptyF{\end{enumerate}}},
+ item-code = \item \dbuse{label},
+ }
+ \dbNewStyle[clist-base]{clist-style1}{clist-db}{
+ label/sep = {{,~}}
+ }
+ \dbNewStyle[clist-base]{clist-style2}{clist-db}{
+ label/sep = {{,~}, {,~}, ~and~}
+ }
+ \dbitemkv{clist-db}{label={a, b, c}}
+ \dbitemkv{clist-db}{label={1, 2, 3}}
+ \dbshow{clist-style1}{clist-db}
+ \dbshow{clist-style2}{clist-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% 参数为4个元素的逗号分隔的列表时,此选项用来设置日期的分隔符,分别用来设
+% 置 \meta{year} 之前的分隔符 \meta{separator before year} ,\meta{year} 和
+% \meta{month} 之间的分隔符 \meta{separator between year and month} ,
+% \meta{month} 和 \meta{day} 之间的分隔符,以及 \meta{day} 之后的分隔符。对于
+% 类型为 |date| 的属性,设置此选项时如果参数列表数量不是1或者4会触发报错。示例
+% \ref{cn-date-sep} 展示了如何自定义日期间隔符。
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(date-sep){设置日期间隔符}
+ \dbNewDatabase{date-db}{date=date}
+ \dbNewStyle{date-style1}{date-db}{
+ item-code = \dbuse{date}\quad,
+ date/sep = -,
+ }
+ \dbNewStyle{date-style2}{date-db}{
+ item-code = \dbuse{date}\quad,
+ date/sep = {\$, +, !, \$},
+ }
+ \dbitemkv{date-db}{date=2020/01/02}
+ \dbitemkv{date-db}{date=2022/07/12}
+ \dbshow{date-style1}{date-db}
+ \dbshow{date-style2}{date-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-14}{Add option}{\opt{<attr>/format-code}}
+% \begin{option}[added=2022-01-14, rEXP]{<attr>/format-code}
+% \begin{syntax}
+% \nopt{<attr>/format-code} = <format code> \inidef
+% \end{syntax}
+%
+% 该选项用来更精细地控制日期的输出格式。在 \meta{format code}中,|#1| 代表年份,
+% |#2| 代表月份,|#3| 代表天。示例 \ref{cn-date-code} 演示了如何使用该选项。
+% \end{option}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(date-code){任意日期格式}
+ \dbNewDatabase{date-db}{date=date}
+ \dbNewStyle{date-style}{date-db}{
+ item-code = \dbuse{date},
+ date/format-code = {日:#3\quad 月:#2\quad 年:#1}
+ }
+ \dbitemkv{date-db}{date=2022/01/01}
+ \dbshow{date-style}{date-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}}
+% \begin{option}[added=2022-01-08, EXP]{<attr>/zfill}
+% \begin{syntax}
+% \nopt{<attr>/zfill} = <\TTF> \inidef(true)[true]
+% \end{syntax}
+%
+% 该选项只适用于类型为 |date| 的属性。控制输出月份和天时是否补零。示例
+% \ref{cn-date-zfill} 展示了补零和不补零的日期。
+% \end{option}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(date-zfill){月份和天补零}
+ \dbNewDatabase{date-db}{date=date}
+ \dbNewStyle {zfill-style}{date-db}{
+ item-code = \dbuse{date},
+ }
+ \dbNewStyle{nofill-style}{date-db}{
+ item-code = \dbuse{date},
+ date/zfill = false,
+ }
+ \dbitemkv{date-db}{date=2022/01/01}
+ \dbshow {zfill-style}{date-db}
+ \dbshow{nofill-style}{date-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbdatesep}}
+% \begin{function}[added=2022-01-13]{\dbdatesep}
+% \begin{syntax}
+% \cs{dbdatesep} \marg{separator}
+% \end{syntax}
+%
+% 设置内部解析日期时的分隔符,默认为 |/|,即存储数据的格式为 |yyyy/mm/dd|。
+% 示例 \ref{cn-inner-date-sep} 演示了使用两种格式存储数据,但实际上分隔符并
+% 没有被存储,而是被内部用来解析年、月和日然后存储为三个整数。
+% \end{function}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(inner-date-sep){设置日期解析格式}
+ \dbNewDatabase{inner-date-db}{date=date}
+ \dbNewStyle{inner-date-style}{inner-date-db}{
+ item-code = \dbuse{date}\quad,
+ }
+ \dbitemkv{inner-date-db}{date=2020/01/20}
+ \dbdatesep{-}
+ \dbitemkv{inner-date-db}{date=2022-01-10}
+ \dbshow{inner-date-style}{inner-date-db}
+\end{example}
+\dbdatesep{/}
+% \iffalse
+%</verb>
+% \fi
+% \subsection{过滤器}
+%
+% 过滤器是一些条件的组合,只有满足过滤器指定条件的数据才会被展现出来。
%
% \begin{function}[added=2022-01-05]{\dbNewReviewPoints}
% \begin{syntax}
% \cs{dbNewReviewPoints} \marg{name} \marg{points}
% \end{syntax}
%
-% 定义名为 \meta{name} 的复习点。这是专门为错题本或复习所定制的功能,
-% \meta{points}是一系列整数,现在假设每道错题你都将写错时的日期记录在了 |date|
-% 属性中,并且你希望每隔2,5,15天复习一次。下面的代码给出了一个实现示例。
+% 定义名为 \meta{name} 的复习间隔列表。\meta{points} 是一系列整数或整数表达
+% 式,用于设置日期的过滤器。示例 \ref{cn-review-points} 中,预定义了一个复习
+% 间隔列表 |review| 和一个时间锚点 |2022/02/06|,筛选时,将当前条目的日期与
+% 描点相比较,计算得到时间间隔 $\meta{interval} = \meta{date anchor} -
+% \meta{date cmp}$,只有当 \meta{interval} 的值在 \meta{points} 中时,条件才
+% 成立。
% \end{function}
%
-% \begin{verbatim}
-% \dbNewReviewPoints{review-point}{2, 5, 15} % 定义复习点
-% \begin{dbFilters}
-% \dbNewConditional{cond1}{date}{review-point|\Today} % 定义复习条件
-% \dbCombineConditionals{filter1}{cond1} % 定义过滤器
-% \end{dbFilters}
-% \dbNewStyle{review-style}{ques}{filter=filter1} % 定义展示样式
-% \end{verbatim}
-%
-% \subsection{在 \env{dbFilters} 环境中定义过滤器}
+% \iffalse
+%<*verb>
+% \fi
+\DeleteShortVerb{\|}
+\begin{example}(review-points){按时间间隔筛选}
+ \dbNewDatabase{filter-db}{date=date}
+ \dbNewReviewPoints{review}{2, 5}
+ \dbNewRawFilter*{review-filter}{filter-db}{date}{review|2022/02/06}
+ \dbNewStyle{filter-style}{filter-db}{
+ item-code = \dbuse{date}\quad,
+ filter = review-filter,
+ }
+ \dbitemkv{filter-db}{date=2022/01/30}
+ \dbitemkv{filter-db}{date=2022/02/01}
+ \dbitemkv{filter-db}{date=2022/02/04}
+ \dbshow{filter-style}{filter-db}
+\end{example}
+\MakeShortVerb{\|}
+% \iffalse
+%</verb>
+% \fi
%
-% \begin{environment}[added=2022-01-05]{dbFilters}
+% \changes{1.5}{2022-01-16}{Update env}{add starred version of \env{dbFilters}}
+% \begin{environment}[added=2022-01-05, updated=2022-01-16]{dbFilters}
% \begin{syntax}
-% |\begin{dbFilters}|\marg{database} \\
+% |\begin|\{\env{dbFilters}\} \marg{database} \\
+% ~~\meta{code}
+% |\end|\{\env{dbFilters}\} \\
+% |\begin|\{\env{dbFilters}\} * \marg{database} \\
% ~~\meta{code}
-% |\end{dbFilters}| \\
+% |\end|\{\env{dbFilters}\} \\
% \end{syntax}
%
% \env{dbFilters}用来定义过滤器,此环境中定义了 \cs{dbNewConditional} 命令用来
-% 定义条件和 \cs{dbCombineConditionals} 命令用来组合条件定义过滤器。过滤器独立
-% 于每个 \meta{database},这意味着你可以在不同数据库中定义名称相同的过滤条件和
-% 过滤器。
+% 定义条件和 \cs{dbCombineConditionals} 命令用来组合条件定义过滤器。星号版本在
+% 定义条件的同时会定义一个与条件同名且只使用这个条件的过滤器。示例
+% \ref{cn-star-filter} 中定义 |greater| 条件的同时也定义了一个同名的过滤器,你
+% 可以直接在 \opt{filter} 中使用这个过滤器。过滤器独立于每个 \meta{database},
+% 这意味着你可以在不同数据库中定义名称相同的过滤条件和过滤器。
% \end{environment}
%
-% \begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(star-filter){定义与条件同名的过滤器}
+ \dbNewDatabase{filter-db}{count=int}
+ \begin{dbFilters}*{filter-db}
+ \dbNewCond{greater}{count}{\dbval > 3}
+ \end{dbFilters}
+ \dbNewStyle{filter-style}{filter-db}{
+ filter = greater,
+ item-code = \dbuse{count}\quad,
+ }
+ \dbitemkv{filter-db}{count=2}
+ \dbitemkv{filter-db}{count=5}
+ \dbshow{filter-style}{filter-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-15}{Add macros}{\cs{dbNewCond}, \cs{dbCombCond}}
+% \begin{function}[added=2022-01-05, updated=2022-01-16]{\dbNewConditional,
+% \dbNewCond, \dbNewConditional*, \dbNewCond*}
% \begin{syntax}
-% \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \\
-% \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \\[2pt]
-% \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \\
-% \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \\
-% \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \\
-% \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \\
-% \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \\
-% \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \\
-% \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr}
-% \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\
+% \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \oarg{filter info} \\[2pt]
+% \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \oarg{filter info}
+% \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \oarg{filter info}
+% \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \oarg{filter info}
+% \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{date expr} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \oarg{filter info}
% \end{syntax}
%
% \cs{dbNewConditional} 用来定义名为 \meta{name} 的条件,\meta{attr} 指定条件
% 所绑定的属性,在 \meta{cond spec} 中可以用 \cs{dbval} 指代属性的值。
+% \cs{dbNewCond} 是 \cs{dbNewConditional} 的别名。
% \end{function}
%
% \changes{1.3}{2022-01-10}{Update doc}{truncated division}
@@ -885,30 +1399,155 @@ Copyright and License
% \end{note}
%
% 对于类型为 |str| 和 |tl| 的属性,\meta{regex} 为正则表达式,
-% \cs{dbNewConditional} 表示部分匹配,\cs{dbNewConditional*} 表示整体匹配。
+% \cs{dbNewConditional} 表示部分匹配,\cs{dbNewConditional*} 表示整体匹配。该
+% 选项依赖于 \pkg{l3regex}。示例 \ref{cn-filter-str} 演示了部分匹配和全部匹
+% 配的区别,|part| 过滤器匹配所有含数字的 |name|,而 |all| 过滤器匹配全部为
+% 数字的 |name|。
%
-% \begin{verbatim}
-% \dbNewConditional {cond1}{str-attr}{abc} % 匹配 abc, abcd, 1abc, =abc= 等
-% \dbNewConditional*{cond2}{str-attr}{abc} % 只匹配 abc
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(filter-str){匹配字符串}
+ \dbNewDatabase{filter-db}{name=str}
+ \begin{dbFilters}*{filter-db}
+ \dbNewCond{part}{name}{\d+}
+ \dbNewCond*{all}{name}{\d+}
+ \end{dbFilters}
+ \dbNewStyle{part-style}{filter-db}{
+ before-code = Match part:~,
+ item-code = \dbuse{name}\quad,
+ filter = part,
+ }
+ \dbNewStyle{all-style}{filter-db}{
+ before-code = Match all:~,
+ item-code = \dbuse{name}\quad,
+ filter = all,
+ }
+ \dbitemkv{filter-db}{name=123}
+ \dbitemkv{filter-db}{name=int12}
+ \dbitemkv{filter-db}{name=variable}
+ \dbshow{part-style}{filter-db}
+ \dbshow {all-style}{filter-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
%
% 对于类型为 |clist| 的属性,使用 \cs{dbNewConditional} 定义的条件只要
% \meta{val list} 中的任意一个元素在属性值(列表)中则条件成立;使用
% \cs{dbNewConditional*} 定义的条件只有 \meta{val list} 中每一个值都在属性值
-% (列表)中条件才成立。
+% (列表)中条件才成立。示例 \ref{cn-filter-clist} 中过滤器 |or| 匹配含有
+% hard \textbf{或者} red 的标签,而过滤器 |and| 匹配含有 hard \textbf{并且}
+% 含有 red 的标签。
%
-% \begin{verbatim}
-% \dbNewConditional {cond1}{clist-attr}{a, b, c} % a, b, d 满足条件
-% \dbNewConditional*{cond2}{clist-attr}{a, b, c} % a, b, d 不满足条件
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(filter-clist){筛选列表}
+ \dbNewDatabase{filter-db}{label=clist}
+ \begin{dbFilters}*{filter-db}
+ \dbNewCond {or}{label}{hard, red}
+ \dbNewCond*{and}{label}{hard, red}
+ \end{dbFilters}
+ \def\emph#1{\textit{\textbf{#1}}}
+ \dbNewStyle{base-style}{filter-db}{
+ before-code = {
+ \begin{minipage}[t]{.3\textwidth}
+ All items
+ },
+ after-code = {\end{minipage}},
+ item-code = \par\dbarabic.~\dbuse{label},
+ }
+ \dbNewStyle[base-style] {or-style}{filter-db}{
+ before-code = {
+ \begin{minipage}[t]{.3\textwidth}
+ Match \emph{any} of hard \emph{or} red
+ },
+ filter = or,
+ }
+ \dbNewStyle[base-style]{and-style}{filter-db}{
+ before-code = {
+ \begin{minipage}[t]{.3\textwidth}
+ Match \emph{all} of hard \emph{and} red
+ },
+ filter = and,
+ }
+ \dbitemkv{filter-db}{label={hard, red}}
+ \dbitemkv{filter-db}{label={hard, blue}}
+ \dbitemkv{filter-db}{label={easy, blue}}
+ \dbitemkv{filter-db}{label={easy, red}}
+ \dbitemkv{filter-db}{label={hard, red, flat}}
+ \dbshow {base-style}{filter-db}
+ \dbshow {or-style}{filter-db}
+ \dbshow {and-style}{filter-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.3}{2022-01-08}{Update logic}{swap definition of starred and
% unstarred conditionals of date}
% 对于类型为 |date| 的属性,\cs{dbNewConditional} 定义的条件后续处理中会将
-% \meta{expr} 中的所有日期转换成相对\textit{1971年1月1日}的一个整数值,然后将
-% 处理后的表达式传递给 \cs{int_compare:nTF} 做进一步处理;
-% \cs{dbNewConditional*} 使用复习点来定义过滤条件,\meta{review points} 是
-% \cs{dbNewReviewPoints} 定义的复习点,\meta{date} 是用来比较的日期。
+% \meta{expr} 中的所有日期转换成相对1971年1月1日的一个整数值,然后将处理后的
+% 表达式传递给 \cs{int_compare:nTF} 做进一步处理。示例 \ref{cn-filter-date}
+% 展示了如何使用该选项。
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(filter-date){根据日期表达式过滤}
+ \dbNewDatabase{filter-db}{date=date}
+ \dbNewRawFilter{date-filter}{filter-db}{date}{\dbval >= 2022/02/01}
+ \dbNewStyle{filter-style}{filter-db}{
+ item-code = \dbuse{date}\quad,
+ filter = date-filter,
+ }
+ \dbitemkv{filter-db}{date=2022/01/30}
+ \dbitemkv{filter-db}{date=2022/02/01}
+ \dbitemkv{filter-db}{date=2022/02/04}
+ \dbshow{filter-style}{filter-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% 对于类型为 |date| 的属性,\cs{dbNewConditional*} 使用复习点来定义过滤条件,
+% \meta{review points} 是 \cs{dbNewReviewPoints} 定义的复习点,\meta{date}
+% 是用来比较的日期(见示例 \ref{cn-review-points})。
+%
+% \changes{1.5}{2022-01-16}{Add macro}{\cs{dbNewRawFilter}}
+% \begin{function}[added=2022-01-16]{\dbNewRawFilter}
+% \begin{syntax}
+% \cs{dbNewRawFilter} \marg{name} \marg{database} \marg{attr} \marg{cond spec} \oarg{filter info}
+% \cs{dbNewRawFilter}* \marg{name} \marg{database} \marg{attr} \marg{cond spec} \oarg{filter info}
+% 等同于
+% |\begin|\{\env{dbFilters}\}*\phantom{\marg{name}}\marg{database}
+% ~~\cs{dbNewCond} \marg{name} \phantom{\marg{database}} \marg{attr} \marg{cond spec} \oarg{filter info}
+% ~~\cs{dbNewCond}* \marg{name} \phantom{\marg{database}} \marg{attr} \marg{cond spec} \oarg{filter info}
+% |\end|\{\env{dbFilters}\}
+% \end{syntax}
+%
+% 该命令用来快捷地定义单个过滤器。示例 \ref{cn-new-raw-filter} 展示了如何使
+% 用该命令,它和示例 \ref{cn-star-filter} 本质上是相同的。
+% \end{function}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(new-raw-filter){定义与条件同名的过滤器}
+ \dbNewDatabase{filter-db}{count=int}
+ \dbNewRawFilter{greater}{filter-db}{count}{\dbval > 3}
+ \dbNewStyle{filter-style}{filter-db}{
+ filter = greater,
+ item-code = \dbuse{count}\quad,
+ }
+ \dbitemkv{filter-db}{count=2}
+ \dbitemkv{filter-db}{count=5}
+ \dbshow{filter-style}{filter-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
%
% \begin{function}[added=2022-01-05]{\dbCombineConditionals}
% \begin{syntax}
@@ -916,37 +1555,60 @@ Copyright and License
% \end{syntax}
%
% \cs{dbCombineConditionals} 定义名为 \marg{name} 的过滤器,并将
-% \cs{dbNewConditional} 定义的条件组合起来,比如
-% \verb=\dbCombineConditionals{filter}{(cond1 && cond2) || !cond3}=。
-% \meta{cond combination} 中可以使用的关系操作符为 \verb=&&, ||, !=。
-% 可以将 \opt{filter} 选项设置为 \meta{name} 来应用过滤器。\meta{info} 为过滤
-% 器的相关信息,在展示数据库的时候可以用 \cs{dbFilterInfo} 指代。
+% \cs{dbNewConditional} 定义的条件组合起来。\meta{cond combination} 中可以使
+% 用的关系操作符为 \verb=&&, ||, !=。可以将 \opt{filter} 选项设置为
+% \meta{name} 来应用过滤器。\meta{info} 为过滤器的相关信息,在展示数据库的时
+% 候可以用 \cs{dbFilterInfo} 指代。使用示例见示例 \ref{cn-filter}.
% \end{function}
%
-% \subsection{使用 \env{dbitem} 环境存储数据}
+% \subsection{存储和使用数据}
%
% \changes{1.4}{2022-01-13}{Update env}{dbitem}
% \begin{environment}[added=2022-01-05, updated=2022-01-13]{dbitem}
% \begin{syntax}
-% |\begin{dbitem}| \marg{database} \oarg{attr-val list}
+% |\begin|\marg{\env{dbitem}} \marg{database} \oarg{attr-val list}
% ~~\meta{code} \\
-% |\end{dbitem}|
+% |\end|\marg{\env{dbitem}}
% \end{syntax}
%
% \env{dbitem} 环境用来存储数据。有两种存储数据的方法,较短的数据可以在选项列
% 表中通过键值对设置值,较长的数据可以在 \meta{code} 中使用 \cs{dbsave} 存储。
% \meta{attr} = \meta{val} 等同于 \cs{dbsave}\marg{attr}\marg{val},
-% \meta{attr}* = \meta{val} 等同于 \cs{dbsave*}\marg{attr}\marg{val},数据在
-% |e| 或者 |x| 类型的参数中不可展开。\cs{dbsave}会覆盖选项中设置的值。没有设
-% 置的值将会被设置为全局默认值,下面给出一个存储示例。
+% \meta{attr}\texttt{*} = \meta{val} 等同于 \cs{dbsave*}\marg{attr}
+% \marg{val},数据在 |e| 或者 |x| 类型的参数中不可展开。\cs{dbsave}会覆盖选
+% 项中设置的值。没有设置的值将会被设置为全局默认值。示例 \ref{cn-dbitem} 展
+% 示了如何存储数据。
% \end{environment}
%
-% \begin{verbatim}
-% \begin{dbitem}[date = 2022-01-01, info = 测试]
-% \dbsave{question}{这是一个测试问题}
-% \dbsave{answer} {这是一个测试答案}
-% \end{dbitem}
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example}(dbitem){存储数据}
+ \dbNewDatabase{ques-db}{date=date, ques=tl, ans=tl}
+ \dbNewStyle{ques-style}{ques-db}{
+ item-code = {%
+ \par\dbuse{date}
+ \par\dbarabic.~\dbuse{ques}
+ \par\textbf{答案:}~\dbuse{ans}
+ },
+ item-after-code = \medskip,
+ date/code* = \zhdate{#1},
+ }
+ \begin{dbitem}{ques-db}[date=2022/01/01]
+ \dbsave{ques}{地球到月亮的距离}
+ \dbsave{ans} {384,401公里}
+ \end{dbitem}
+ \begin{dbitem}{ques-db}[date=2022/01/02]
+ \dbsave{ques}{鲁迅的本名}
+ \dbsave{ans} {周树人}
+ \end{dbitem}
+ \dbshow{ques-style}{ques-db}
+\end{example}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbitemkv}}
% \begin{function}[added=2022-01-13]{\dbitemkv}
@@ -957,8 +1619,6 @@ Copyright and License
% 只使用 \meta{attr-val list} 来存储数据。
% \end{function}
%
-% \subsection{\cs{dbsave} 和 \cs{dbuse}}
-%
% \changes{1.3}{2022-01-08}{Add macro}{\cs{dbsave*}}
% \begin{function}[added=2022-01-05, updated=2022-01-08]{\dbsave, \dbsave*}
% \begin{syntax}
@@ -976,8 +1636,8 @@ Copyright and License
% \cs{dbuse} \marg{attr}
% \end{syntax}
%
-% \cs{dbuse} 用来展示数据,只能在 \opt{item-code} 选项中使用。\cs{dbuse} 是可
-% 展开的。
+% \cs{dbuse} 用来展示数据,只能在 \opt{item-code}, \opt{item-before-code},
+% \opt{item-after-code} 选项中使用。\cs{dbuse} 是可展开的。
% \end{function}
%
% \subsection{条件判别式}
@@ -985,20 +1645,69 @@ Copyright and License
% \begin{function}[added=2022-01-05, EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF}
% \begin{syntax}
% \cs{dbIfEmptyTF} \marg{true code} \marg{false code} \\
-% \cs{dbIfEmptyT} \marg{true code} \\
+% \cs{dbIfEmptyT} \marg{true code} \\
% \cs{dbIfEmptyF} \marg{false code}
% \end{syntax}
%
-% 该判别式用来判断当前数据库是否为空。下面的示例展示了如何预防空的列表环境。
+% 该判别式用来判断当前数据库是否为空。示例 \ref{cn-empty-db} 演示了如何使用
+% 该判别式来预防空的列表环境。
% \end{function}
%
-% \begin{verbatim}
-% \dbNewStyle{style-cond1}{database-test}{
-% before-code = {\dbIfEmptyF{\begin{enumerate}}},
-% after-code = {\dbIfEmptyF{\end{enumerate}}},
-% item-code = {\item \dbuse{attr-test}}
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(empty-db){预防空列表环境}
+ \dbNewDatabase{test-db}{text=tl}
+ \dbNewRawFilter{alph}{test-db}{text}{\d}
+ \dbNewStyle{base-style}{test-db}{
+ before-code = \dbIfEmptyTF{Empty db}{\begin{enumerate}},
+ after-code = \dbIfEmptyF{\end{enumerate}}\medskip,
+ item-code = \item \dbuse{text},
+ }
+ \dbNewStyle[base-style]{empty-style}{test-db}{
+ raw-filter=!alph
+ }
+ \dbitemkv{test-db}{text={$1 + 1 = 2$.}}
+ \dbitemkv{test-db}{text={I have 2 pens.}}
+ \dbshow {base-style}{test-db}
+ \dbshow{empty-style}{test-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-17}{Add macros}{\cs{dbIfLastT}, \cs{dbIfLastF},
+% \cs{dbIfLastTF}}
+% \begin{function}[added=2022-01-17, EXP]{\dbIfLastT, \dbIfLastF, \dbIfLastTF}
+% \begin{syntax}
+% \cs{dbIfLastTF} \marg{true code} \marg{false code}
+% \cs{dbIfLastT} \marg{true code}
+% \cs{dbIfLastF} \marg{false code}
+% \end{syntax}
+%
+% 该判别式用来判断当前是否为数据库要展示的最后一条数据。示例
+% \ref{cn-last} 演示了如何设置条目之间的间隔。
+% \end{function}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(last){设置条目之间的间隔}
+ \dbNewDatabase{last-db}{text=tl}
+ \dbNewStyle{last-style}{last-db}{
+ item-code = {%
+ \par\dbuse{text}\par%
+ \dbIfLastF{\textcolor{red}{\hrulefill separator\hrulefill}}%
+ },
+ }
+ \dbitemkv{last-db}{text=This is the first paragraph.}
+ \dbitemkv{last-db}{text=This is the second paragraph.}
+ \dbitemkv{last-db}{text=This is the last paragraph.}
+ \dbshow{last-style}{last-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}}
%
@@ -1010,26 +1719,49 @@ Copyright and License
% \dbIntMin, \dbIntMod, \dbFpSign,
% }
% \begin{syntax}
-% \cs{dbIntAbs} \Arg{intexpr}
-% \cs{dbIntSign} \Arg{intexpr}
-% \cs{dbIntDivRound} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntDivTruncate} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntMax} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntMin} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntMod} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbFpSign} \Arg{fpexpr}
-% \end{syntax}
-% \cs{dbIntAbs} 等同于 \cs{int_abs:n} \\
-% \cs{dbIntSign} 等同于 \cs{int_sign:n} \\
-% \cs{dbIntDivRound} 等同于 \cs{int_div_round:nn} \\
-% \cs{dbIntDivTruncate} 等同于 \cs{int_div_truncate:nn} \\
-% \cs{dbIntMax} 等同于 \cs{int_max:nn} \\
-% \cs{dbIntMin} 等同于 \cs{int_min:nn} \\
-% \cs{dbIntMod} 等同于 \cs{int_mod:nn} \\
-% \cs{dbFpSign} 等同于 \cs{fp_sign:n} \\
-% 详细的文档见 \pkg{interface3} \\
+% \cs{dbIntAbs} \Arg{intexpr}
+% \cs{dbIntSign} \Arg{intexpr}
+% \cs{dbIntDivRound} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntDivTruncate} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntMax} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntMin} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntMod} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbFpSign} \Arg{fpexpr}
+% \end{syntax}
+% \begin{tblr}{ll}
+% \cs{dbIntAbs} & 等同于 \cs{int_abs:n} \\
+% \cs{dbIntSign} & 等同于 \cs{int_sign:n} \\
+% \cs{dbIntDivRound} & 等同于 \cs{int_div_round:nn} \\
+% \cs{dbIntDivTruncate} & 等同于 \cs{int_div_truncate:nn} \\
+% \cs{dbIntMax} & 等同于 \cs{int_max:nn} \\
+% \cs{dbIntMin} & 等同于 \cs{int_min:nn} \\
+% \cs{dbIntMod} & 等同于 \cs{int_mod:nn} \\
+% \cs{dbFpSign} & 等同于 \cs{fp_sign:n} \\
+% \end{tblr}
+%
+% 详细的文档见 \pkg{interface3}。示例 \ref{cn-expr-db} 展示了如何筛选3的倍数。
% \end{function}
%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example}(expr-db){筛选3的倍数}
+ \dbNewDatabase{expr-db}{n=int}
+ \dbNewRawFilter{mod}{expr-db}{n}{\dbIntMod{\dbval}{3} = 0}
+ \dbNewStyle{expr-style}{expr-db}{
+ item-code = \dbuse{n}\quad,
+ filter = mod,
+ }
+ \dbitemkv{expr-db}{n=2}
+ \dbitemkv{expr-db}{n=3}
+ \dbitemkv{expr-db}{n=6}
+ \dbitemkv{expr-db}{n=7}
+ \dbshow{expr-style}{expr-db}
+\end{example}
+% \iffalse
+%</verb>
+% \fi
+%
% \subsection{特殊命令}
%
% \pkg{dbshow} 定义了一些特殊的命令,会根据语境展开为不同的内容。
@@ -1040,27 +1772,64 @@ Copyright and License
% }
% \changes{1.1}{2022-01-06}{Fix bug}{\cs{dbIndex} not defined}
% \begin{function}[added=2022-01-05, EXP]{
-% \dbval, \dbDatabase, \dbFilterName, \dbFilterInfo,
+% \dbval, \dbtoday, \dbDatabase, \dbFilterName, \dbFilterInfo,
% \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman
% }
% \begin{tblr}{ll}
-% \cs{dbval} & 当前属性的值 \\
-% \cs{dbDatabase} & 数据库名称 \\
+% \cs{dbval} & 当前属性的值 \\
+% \cs{dbtoday} & 当天的日期 \\
+% \cs{dbDatabase} & 数据库名称 \\
% \cs{dbFilterName} & 当前样式过滤器的名称 \\
% \cs{dbFilterInfo} & 当前样式过滤器的相关信息 \\
-% \cs{dbIndex} & 数据索引,等同于 \cs{dbuse}|{id}| \\
-% \cs{dbarabic} & 用数字表示的查询集数据计数 \\
-% \cs{dbalph} & 用小写字母表示的查询集数据计数 \\
-% \cs{dbAlph} & 用大写字母表示的查询集数据计数 \\
-% \cs{dbroman} & 用小写罗马字母表示的查询集数据计数 \\
-% \cs{dbroman} & 用大写罗马字母表示的查询集数据计数 \\
-% \end{tblr}
+% \cs{dbIndex} & 数据索引,等同于 \cs{dbuse}\marg{id} \\
+% \cs{dbarabic} & 用数字表示的查询集数据计数 \\
+% \cs{dbalph} & 用小写字母表示的查询集数据计数 \\
+% \cs{dbAlph} & 用大写字母表示的查询集数据计数 \\
+% \cs{dbroman} & 用小写罗马字母表示的查询集数据计数 \\
+% \cs{dbroman} & 用大写罗马字母表示的查询集数据计数 \\
+% \end{tblr}
+%
+% \cs{dbtoday} 使用 \cs{dbdatesep} 确定的分隔符来展示日期。见示例
+% \ref{cn-spespecial-cs}.
% \end{function}
%
-% \section{错题本示例}
-% 见第 \ref{sec:example} 节。
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example}(special-cs){特殊命令}
+ \dbNewDatabase{special-db}{name=str}
+ \dbNewRawFilter*{number}{special-db}{name}{\d+}[name that is a number]
+ \dbNewStyle{special-style}{special-db}{
+ before-code = {
+ Date: \dbtoday \\
+ Database: \dbDatabase
+ Filter: \dbFilterName \\
+ Filter info: \dbFilterInfo \par
+ \begin{tabular}{@{}lllllll}
+ Index & arabic & alph & Alph & roman & Roman & value \\
+ },
+ after-code = \end{tabular},
+ item-code* = {%
+ \dbIndex & \dbarabic & \dbalph & \dbAlph &
+ \dbroman & \dbRoman & \dbuse{name} \\
+ },
+ sort = name,
+ filter = number,
+ }
+ \dbitemkv{special-db}{name=test}
+ \dbitemkv{special-db}{name=12}
+ \dbitemkv{special-db}{name=int2}
+ \dbitemkv{special-db}{name=99}
+ \dbshow{special-style}{special-db}
+\end{example}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.1}{2022-01-07}{Update doc}{improve example}
+% \changes{1.5}{2022-01-17}{Remove doc}{Remove big example}
%
% \title{
% Package \pkg{dbshow} \fileversion%
@@ -1085,7 +1854,7 @@ Copyright and License
% certain times or questions having not been reviewed for certain days. So this
% package provides a database to do such thing.
%
-% The package provides four core functions: data storage and display, data
+% The package provides four core functions: data storage, data
% filtering, data sorting and data display. All data is saved once and then you
% can display these data with custom filters, orders and styles.
%
@@ -1129,23 +1898,8 @@ Copyright and License
% by \pkg{dbshow} itself and supports converting to integer and printing with
% style.
%
-% \subsection{Comparison to \pkg{datatool}}
-%
% \changes{1.2}{2022-01-07}{Add doc}{add comparison to \pkg{datatool}}
-%
-% \pkg{dbshow} and \pkg{datatool} implement the same core functions. But
-% \pkg{dbshow} is based on \pkg{expl3} and it supports string regex and
-% multi-level sorting. \pkg{dbshow} tries to divide style from the contents
-% (data in database): all styles are predefined and can be reused conveniently
-% so that there can be only codes to save data and one-line code to show the
-% database inside the \env{document} environment. You can hide the details in
-% the preamble and focus on the data you want to display. \pkg{dbshow} provides
-% a simple temporary runtime database, which means it can not input and output
-% data from/to extern files (they should be responsible by some professional
-% programming languages). When you need to delete or revise a record, just go to
-% where it is recorded in the source code rather than use a macro to manipulate
-% data after they are saved. In a sense, \TeX~file is also a kind of data
-% persistence.
+% \changes{1.3}{2022-01-07}{Remove doc}{remove comparison to \pkg{datatool}}
%
% \section{Interfaces}
%
@@ -1186,17 +1940,6 @@ Copyright and License
% Every database has a default attribute |id| to store the index of the item.
% \end{note}
%
-% The example below define a database named |ques|.
-% \begin{verbatim}
-% \dbNewDatabase{ques}{
-% question = tl, % store question
-% answer = tl, % store corresponding answer
-% date = date, % store the date when you were wrong
-% info = tl, % store extra info
-% labels = clist % store question labels
-% }
-% \end{verbatim}
-%
% \begin{function}[added=2022-01-05]{\dbshow}
% \begin{syntax}
% \cs{dbshow} \marg{style} \marg{database}
@@ -1216,7 +1959,7 @@ Copyright and License
%
% \subsection{\cs{dbNewStyle} and Style Options}
%
-% \begin{function}[added=2022-01-05]{\dbNewStyle}
+% \begin{function}[added=2022-01-05, updated=2022-01-15]{\dbNewStyle}
% \begin{syntax}
% \cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts}
% \end{syntax}
@@ -1230,253 +1973,412 @@ Copyright and License
%
% \begin{option}[added=2022-01-05]{filter}
% \begin{syntax}
-% filter = <filter>
+% \opt{filter} = <filter> \inidef(-none-)
% \end{syntax}
%
-% Set the \meta{filter} defined by \cs{dbCombineFilters}.
+% Set the \meta{filter} defined by \cs{dbCombineFilters}. Example
+% \ref{en-filter} shows how to define conditionals and combine them into
+% a filter.
% \end{option}
%
+% \DeleteShortVerb{\|}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(filter){Filter Items}
+ \dbNewDatabase{filter-db}{name=str, count=int}
+ \begin{dbFilters}{filter-db}
+ \dbNewCond {cond1}{count}{\dbval > 3}
+ \dbNewCond*{cond2}{name} {\d+}
+ \dbCombCond{filter-and}{cond1 && cond2}
+ \dbCombCond{filter-or} {cond1 || cond2}
+ \end{dbFilters}
+ \dbitemkv{filter-db}{name=123, count=4}
+ \dbitemkv{filter-db}{name=ab3, count=2}
+ \dbitemkv{filter-db}{name=bag, count=5}
+ \dbNewStyle{filter-and-style}{filter-db}{
+ filter = filter-and,
+ before-code = \par Filter And\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbNewStyle{filter-or-style}{filter-db}{
+ filter = filter-or,
+ before-code = \par Filter Or\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbshow{filter-and-style}{filter-db}
+ \dbshow{filter-or-style} {filter-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+% \MakeShortVerb{\|}
+%
% \changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}}
% \begin{option}[added=2022-01-06]{raw-filter}
% \begin{syntax}
-% raw-filter = <conditional expression>
+% \opt{raw-filter} = <conditional expression> \inidef
% \end{syntax}
%
-% Set anonymous with conditionals defined by \cs{dbNewConditional}. Two
-% filters shows in the code below have the same meaning.
+% Set anonymous filter with conditionals defined by \cs{dbNewConditional}.
+% Example \ref{en-raw-filter} shows how to simplify the code of example
+% \ref{en-filter} with \opt{raw-filter} option.
% \end{option}
%
-% \begin{verbatim}
-% % method 1
-% \begin{dbFilters}{db}
-% \dbNewConditional{cond1}{int-attr}{\rval > 1}
-% \dbNewConditional*{cond2}{str-attr}{\d+}
-% \end{dbFilters}
-% \dbNewStyle{style}{db}{raw-filter={cond1 && cond2}}
-% % method 2
-% \begin{dbFilters}{db}
-% \dbNewConditional{cond1}{int-attr}{\rval > 1}
-% \dbNewConditional*{cond2}{str-attr}{\d+}
-% \dbCombineFilters{filter}{cond1 && cond2}
-% \end{dbFilters}
-% \dbNewStyle{style}{db}{filter=filter}
-% \end{verbatim}
+% \DeleteShortVerb{\|}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(raw-filter){Using Anonymous Filter}
+ \dbNewDatabase{filter-db}{name=str, count=int}
+ \begin{dbFilters}{filter-db}
+ \dbNewCond {cond1}{count}{\dbval > 3}
+ \dbNewCond*{cond2}{name} {\d+}
+ \end{dbFilters}
+ \dbitemkv{filter-db}{name=123, count=4}
+ \dbitemkv{filter-db}{name=ab3, count=2}
+ \dbitemkv{filter-db}{name=bag, count=5}
+ \dbNewStyle{filter-and-style}{filter-db}{
+ raw-filter = {cond1 && cond2},
+ before-code = \par Filter And\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbNewStyle{filter-or-style}{filter-db}{
+ raw-filter = {cond1 || cond2},
+ before-code = \par Filter Or\par,
+ item-code = {\dbuse{name}: \dbuse{count}\quad},
+ }
+ \dbshow{filter-and-style}{filter-db}
+ \dbshow{filter-or-style} {filter-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+% \MakeShortVerb{\|}
%
% \changes{1.2}{2022-01-08}{Fix bug}{string sorting bug}
% \begin{option}[added=2022-01-05]{sort}
% \begin{syntax}
-% sort = \{ <attr spec1>, <attr spec2>, \ldots{} \}
+% \opt{sort} = \{ <attr spec1>, <attr spec2>, \ldots{} \} \inidef
% \end{syntax}
%
% Set sorting rules. Attributes of type |str, date, int, fp| is supported to
-% sort. Multi-level sort is allowed. \meta{attr} represents for ascending
-% order, and \meta{attr}* represents for descending order. The example below
-% use four fields to determine the order of the records. It sorts on |level|
-% in descending order first and if two |levels| are same then sorts on |birth|
-% in ascending order and so on.
+% sort. Multi-level sort is allowed. \meta{attr} represents for ascending
+% order, and \meta{attr}\texttt{*} represents for descending order. Example
+% \ref{en-sort} shows how to sort items by |count| in descending order and
+% for the same |count|, sort by |name| in ascending order.
% \end{option}
%
-% \begin{verbatim}
-% \dbNewDatabase{sort-example}{
-% name = str,
-% birth = date,
-% level = int,
-% weight = fp,
-% }
-% \dbNewStyle{sort-style}{sort-example}{
-% sort = { level*, birth, name, weight }
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(sort){Multi-level Sorting}
+ \dbNewDatabase{sort-db}{name=str, count=int}
+ \dbNewStyle{sort-style}{sort-db}{
+ sort = {count*, name},
+ item-code = {\dbuse{name}: \dbuse{count}\quad}
+ }
+ \dbitemkv{sort-db}{name=bag, count=1}
+ \dbitemkv{sort-db}{name=box, count=1}
+ \dbitemkv{sort-db}{name=tag, count=2}
+ \dbitemkv{sort-db}{name=pen, count=3}
+ \dbshow{sort-style}{sort-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
%
-% \begin{option}[added=2022-01-05, rEXP]{item-code}
+% \begin{option}[added=2022-01-05, rEXP]{before-code}
% \begin{syntax}
-% item-code = <code>
+% \opt{before-code} = <before code> \inidef*
% \end{syntax}
%
-% Set the code that show a single record. You can use \cs{dbuse} to display
-% certian attribute.
+% Set the \meta{code} that is executed \enbefore displaying the database.
+% See Example \ref{en-db-wrap}.
% \end{option}
%
-% \changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}}
-% \begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep}
+% \begin{option}[added=2022-01-05, rEXP]{after-code}
% \begin{syntax}
-% <attr>/sep = <separator> \\
-% <attr>/sep = \{ \\
-% ~~\meta{separator between two}, \\
-% ~~\meta{separator between more than two}, \\
-% ~~\meta{separator between final two} \\
-% \} \\
-% <attr>/sep = \{ \\
-% ~~\meta{separator before year}, \\
-% ~~\meta{separator between year and month}, \\
-% ~~\meta{separator between month and day}, \\
-% ~~\meta{separator after day} \\
-% \} \\
+% \opt{after-code} = <after code> \inidef*
% \end{syntax}
%
-% Only for attributes of type |clist| or |date|. Set the separator between
-% items. If the argument is an one-item comma list, all separators are set to
-% \meta{separator} but \meta{separator before year} and \meta{separator after
-% day} is set empty.
+% Set the \meta{code} that is executed \enafter displaying the database.
+% See Example \ref{en-db-wrap}.
% \end{option}
%
-% If the argument is a comma list of 3 items, it is used to set the separator
-% between items of the comma list. Following documentation is quoted from
-% \pkg{interface3}:
-% \begin{quote}
-% If the comma list has more than two items, the \meta{separator between
-% more than two} is placed between each pair of items except the last, for
-% which the \meta{separator between final two} is used. If the comma list
-% has exactly two items, then they are placed in the input stream separated
-% by the \meta{separator between two}. If the comma list has a single item,
-% it is placed in the input stream, and a comma list with no items produces
-% no output.
-% \end{quote}
-% For attributes of type |clist|, incorrect number (numbers exclude 1 and 3)
-% of items of the argument will raise an error.
-%
-% \begin{verbatim}
-% % clist-attr is an attribute of database db
-% % suppose the val of clist-attr is { 1, 2, 3 }
-% \dbNewStyle{clist-sep}{db}{
-% clist-attr/sep = { ,~ }, % print 1, 2, 3
-% clist-attr/sep = { {,~}, {,~}, {and~} } % print 1, 2 and 3
-% }
-% \end{verbatim}
-%
-% If the argument is a comma list of 4 items, it is used to set the separators
-% of the date. For attributes of type |date|, incorrect number (numbers
-% exclude 1 and 4) will raise an error.
-%
-% \begin{verbatim}
-% % date-attr is an attribute of database db
-% % suppose the val of date-attr is 2022/01/01
-% \dbNewStyle{date-sep}{db}{
-% date-attr/sep = -, % print 2022-01-01
-% date-attr/sep = { |, -, -, | } % print |2022-01-01|
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(db-wrap){Set the Before and After Code of the Database}
+ \dbNewDatabase{wrap-db}{text=tl}
+ \dbNewStyle{wrap-style}{wrap-db}{
+ before-code = \textit{before code}\quad,
+ after-code = \textit{after code},
+ item-code = \dbarabic.~\dbuse{text}\quad
+ }
+ \dbitemkv{wrap-db}{text=text1}
+ \dbitemkv{wrap-db}{text=text2}
+ \dbitemkv{wrap-db}{text=text3}
+ \dbshow{wrap-style}{wrap-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
%
-% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}}
-% \begin{option}[added=2022-01-08, EXP]{<attr>/zfill}
+% \begin{option}[added=2022-01-05, rEXP]{item-code}
% \begin{syntax}
-% <attr>/zfill = <\TTF>
+% \opt{item-code} = <item code> \inidef
% \end{syntax}
%
-% Only for attributes of type |date|. Control whether to fill zero on the left
-% of the month or day.
+% Set the code that display a record. You can use \cs{dbuse} to denote the
+% value of attribute. Example \ref{en-item-code} shows how to display an
+% acronym glossary table.
% \end{option}
%
-% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbdatesep}}
-% \begin{function}[added=2022-01-13, EXP]{\dbdatesep}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(item-code){Display Database Items}
+ \dbNewDatabase{item-db}{acronym=str, desc=tl}
+ \dbNewStyle{item-style}{item-db}{
+ before-code = {\dbIfEmptyF{\begin{description}}},
+ after-code = {\dbIfEmptyF{\end{description}}},
+ item-code = {\item[\dbuse{acronym}] \dbuse{desc}},
+ sort = acronym,
+ }
+ \dbitemkv{item-db}{acronym=PM, desc={Prime Minister}}
+ \dbitemkv{item-db}{acronym=CBD, desc={Central Business District}}
+ \dbitemkv{item-db}{acronym=DL, desc={Deep Learning}}
+ \dbshow{item-style}{item-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-17}{Add option}{\opt{item-code*}}
+% \begin{option}[added=2022-01-17, rEXP]{item-code*}
% \begin{syntax}
-% \cs{dbdatesep} \marg{separator}
+% \opt{item-code*} = <item code> \inidef
% \end{syntax}
%
-% Set the separator for internal date parsing. The default value is |/|,
-% i.e. the date must be store in the format of |yyyy/mm/dd|.
-% \end{function}
+% The \meta{item code} will be expanded through \cs{protected@edef} before
+% it is used. \ref{en-item-exp} shows how to display data with table using
+% the expanded code.
+% \end{option}
%
-% \subsubsection{Decorators}
-%
-% The options below serves as decorators. In some cases, decorator can also be
-% encoded directly into |item-code| or some other places, which is convenient
-% sometimes. The benefit of defining decorators with options is that styles step
-% further to be divided with contents. In the examples below, \meta{style1} and
-% \meta{style2} is the same style, which wrap \meta{attr1} with *. When you want
-% another style which wrap \meta{attr1} with =, if you choose the way of
-% \meta{style1}, \meta{item code} are repeated, otherwise if you choose the way
-% of \meta{style2}, \meta{item code} is inherited and you only need define the
-% decorators.
-%
-% \begin{verbatim}
-% \dbNewStyle{style1}{db}{
-% item-code = {%
-% *\rvuse{attr1}*\rvuse{attr2}
-% % more code
-% }
-% }
-% \dbNewStyle{base-style}{db}{
-% item-code = {%
-% \rvuse{attr1}\rvuse{attr2}
-% % more code
-% }
-% }
-% \dbNewStyle[base-style]{style2}{db}{
-% attr1/before-code = { * },
-% attr1/after-code = { * },
-% }
-% \dbNewStyle[base-style]{style3}{db}{
-% attr1/before-code = { = },
-% attr1/after-code = { = },
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example*}(item-exp){Display Data with Table}
+ \dbNewDatabase{tab-db}{name=str, count=int}
+ \dbNewStyle{tab-style}{tab-db}{
+ before-code = {%
+ \begin{tabular}{ll}
+ name & count \\
+ },
+ after-code = \end{tabular},
+ item-code* = {%
+ \textcolor{red}{\dbuse{name}} & \dbuse{count} \\
+ },
+ }
+ \dbitemkv{tab-db}{name=bag, count=100}
+ \dbitemkv{tab-db}{name=pig, count=20}
+ \dbshow{tab-style}{tab-db}
+\end{example*}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
%
-% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}}
-% \begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper}
+% \changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code},
+% \opt{record-after-code}}
+% \changes{1.5}{2022-01-14}{Update options}{Rename \opt{record-before-code}
+% and \opt{record-after-code} to \opt{item-before-code} and
+% \opt{item-after-code}}
+% \begin{option}[added=2022-01-08, updated=2022-01-14, rEXP]{item-before-code}
% \begin{syntax}
-% <attr>/wrapper = <control sequence>
+% \opt{item-before-code} = <before code> \inidef*
% \end{syntax}
%
-% Only for attributes of type |date|. Output of \cs{dbuse}\marg{date attr}
-% will be \meta{control sequence}\marg{date}.
+% Set the \meta{code} that is executed \enbefore displaying a item. See
+% Example \ref{en-item-wrapper}.
% \end{option}
%
-% \begin{option}[added=2022-01-05, rEXP]{before-code}
+% \begin{option}[added=2022-01-08, updated=2022-01-14, rEXP]{item-after-code}
% \begin{syntax}
-% before-code = <code>
+% \opt{item-after-code} = <after code> \inidef*
% \end{syntax}
%
-% Set the \meta{code} that is executed \enbefore displaying the database.
+% Set the \meta{code} that is executed \enafter displaying the item. See
+% Example \ref{en-item-wrapper}.
% \end{option}
%
-% \begin{option}[added=2022-01-05, rEXP]{after-code}
-% \begin{syntax}
-% after-code = <code>
-% \end{syntax}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(item-wrapper){Set the Before and After Code of the Item}
+ \dbNewDatabase{item-wrap-db}{text=tl}
+ \dbNewStyle{item-wrap-style}{item-wrap-db}{
+ item-before-code = \begingroup\ttfamily<,
+ item-after-code = >\endgroup,
+ item-code = \dbuse{text},
+ }
+ \dbitemkv{item-wrap-db}{text=example}
+ \dbshow{item-wrap-style}{item-wrap-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
%
-% Set the \meta{code} that is executed \enafter displaying the database.
-% \end{option}
+% \subsubsection{Attribute Options}
%
-% \changes{1.2}{2022-01-08}{Add options}{\opt{record-before-code},
-% \opt{record-after-code}}
-% \begin{option}[added=2022-01-05, rEXP]{record-before-code}
+% \changes{1.5}{2022-01-14}{Remove option}{\opt{<attr>/wrapper}}
+%
+% \changes{1.5}{2022-01-14}{Add options}{\opt{<attr>/code},
+% \opt{<attr>/code*}}
+% \begin{option}[added=2022-01-14, rEXP]{<attr>/code}
% \begin{syntax}
-% record-before-code = <code>
+% \nopt{<attr>/code} = <code> \inidef(\#1)
% \end{syntax}
%
-% Set the \meta{code} that is executed \enbefore displaying a record.
+% Set the style code of \meta{attr}. In \meta{code}, |#1| is replaced with the
+% value of \meta{attr}. Example \ref{en-attr-code} prints |name| whose |count|
+% is less than 10 in teal color, otherwise in red color.
% \end{option}
%
-% \begin{option}[added=2022-01-05, rEXP]{record-after-code}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(attr-code){Set Style Code of Attribute}
+ \dbNewDatabase{attr-code-db}{name=str, count=int}
+ \begin{dbFilters}{attr-code-db}
+ \dbNewCond{large}{count}{\dbval >= 10}
+ \end{dbFilters}
+ \dbNewStyle{base-style}{attr-code-db}{
+ item-code = \dbuse{name}:~\dbuse{count}\quad,
+ }
+ \dbNewStyle[base-style]{large-style}{attr-code-db}{
+ raw-filter = large,
+ name/code = \textcolor{red}{#1},
+ }
+ \dbNewStyle[base-style]{small-style}{attr-code-db}{
+ raw-filter = !large,
+ name/code = \textcolor{teal}{#1},
+ }
+ \dbitemkv{attr-code-db}{name=bag, count=1}
+ \dbitemkv{attr-code-db}{name=pen, count=12}
+ \dbitemkv{attr-code-db}{name=pig, count=5}
+ \dbitemkv{attr-code-db}{name=egg, count=50}
+ \dbshow{large-style}{attr-code-db}
+ \dbshow{small-style}{attr-code-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \begin{option}[added=2022-01-14, rEXP]{<attr>/code*}
% \begin{syntax}
-% record-after-code = <code>
+% \nopt{<attr>/code*} = <code> \inidef
% \end{syntax}
%
-% Set the \meta{code} that is executed \enafter displaying the record.
+% Set the style code of \meta{attr}. In \meta{code}, |#1| is replaced with the
+% \textbf{expanded} value of \meta{attr}. This is useful to commands that
+% require special format of the arguments.
% \end{option}
%
+% Example \ref{en-exp-code} shows how to print Chinese date with \cs{zhdate}
+% of package \pkg{zhnumber}. \cs{zhdate} require argument to be the date of
+% |yyyy/mm/dd|, which is the default date format of \pkg{dbshow}. But we need
+% to expand the date through \opt{date/code*} first because \cs{zhdate} cannot
+% parse the token list other than |yyyy/mm/dd|.
+%
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example*}(exp-code){Show Chinese Date}
+ % \usepackage{zhnumber}
+ \dbNewDatabase{exp-db}{date=date, event=tl}
+ \dbNewStyle{exp-style}{exp-db}{
+ item-code = \par\makebox[4cm][l]{\dbuse{date}}\dbuse{event},
+ date/code* = \zhdate{#1},
+ }
+ \dbitemkv{exp-db}{date=2020/12/31, event=eat}
+ \dbitemkv{exp-db}{date=2021/01/01, event=sleep}
+ \dbshow{exp-style}{exp-db}
+\end{example*}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
+%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/before-code}
% \begin{syntax}
-% <attr>/before-code = <code>
+% \nopt{<attr>/before-code} = <before code> \inidef*
% \end{syntax}
%
% Set the \meta{code} that is executed by \cs{dbuse} \enbefore displaying
-% certain attribute.
+% the value of attribute.
% \end{option}
%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/after-code}
% \begin{syntax}
-% <attr>/after-code = <code>
+% \nopt{<attr>/after-code} = <after code> \inidef*
% \end{syntax}
%
% Set the \meta{code} that is executed by \cs{dbuse} \enafter displaying
-% certain attribute.
+% the value of attribute.
+% \end{option}
+%
+% The style code execution order of attribute is:
+% \begin{enumerate}[nolistsep]
+% \item \opt{<attr>/before-code}
+% \item \opt{<attr>/code} or \opt{<attr>/code*}
+% \item \opt{<attr>/after-code}
+% \end{enumerate}
+%
+% \changes{1.5}{2022-01-16}{Add options}{\opt{<attr>/item-code},
+% \opt{<attr>/item-code*}}
+% \begin{option}[added=2022-01-16, rEXP]{<attr>/item-code}
+% \begin{syntax}
+% \nopt{<attr>/item-code} = <item code> \inidef(\#1)
+% \end{syntax}
+%
+% Set the style code of \meta{attr}. In \meta{item code}, |#1| is replaced
+% with the item of the comma list. Example \ref{en-clist-code} shows how to
+% set the style code of the item of the comma list.
+% \end{option}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(clist-code){Set the Style Code of Clist Item}
+ \dbNewDatabase{clist-db}{name=str, label=clist}
+ \dbNewStyle{clist-style}{clist-db}{
+ item-code = \par\dbuse{name}:~\dbuse{label},
+ label/item-code = (\textcolor{red}{\textit{#1}}),
+ }
+ \dbitemkv{clist-db}{name=pig, label={animal, meat}}
+ \dbitemkv{clist-db}{name=Alex, label={person, male}}
+ \dbshow{clist-style}{clist-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \begin{option}[added=2022-01-16, rEXP]{<attr>/item-code*}
+% \begin{syntax}
+% \nopt{<attr>/item-code*} = <item code> \inidef
+% \end{syntax}
+%
+% Set the style code of \meta{attr}. In \meta{item code}, |#1| is replaced
+% with the \textbf{expanded} item of the comma list.
% \end{option}
%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code}
% \begin{syntax}
-% <attr>/item-before-code = <code>
+% \nopt{<attr>/item-before-code} = <before code> \inidef*
% \end{syntax}
%
% Only for attributes of type |clist|. Set the \meta{code} that is excuted
@@ -1485,63 +2387,297 @@ Copyright and License
%
% \begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code}
% \begin{syntax}
-% <attr>/item-after-code = <code>
+% \nopt{<attr>/item-after-code} = <after code> \inidef*
% \end{syntax}
%
% Only for attributes of type |clist|. Set the \meta{code} that is excuted
% \enafter displaying the item of the comma list.
% \end{option}
%
-% \subsection{Use \cs{dbNewReviewPoints} to Define Review Points}
+% The style code execution order of comma list item is:
+% \begin{enumerate}[nolistsep]
+% \item \opt{<attr>/item-before-code}
+% \item \opt{<attr>/item-code} or \opt{<attr>/item-code*}
+% \item \opt{<attr>/item-after-code}
+% \end{enumerate}
+%
+% \changes{1.3}{2022-01-09}{Update option}{\opt{<attr>/sep}}
+% \begin{option}[added=2022-01-05, updated=2022-01-08, rEXP]{<attr>/sep}
+% \begin{syntax}
+% \nopt{<attr>/sep} = <separator> \sepini\\
+% \nopt{<attr>/sep} = \{ \\
+% ~~\meta{separator between two}, \\
+% ~~\meta{separator between more than two}, \\
+% ~~\meta{separator between final two} \\
+% \} \\
+% \nopt{<attr>/sep} = \{ \\
+% ~~\meta{separator before year}, \\
+% ~~\meta{separator between year and month}, \\
+% ~~\meta{separator between month and day}, \\
+% ~~\meta{separator after day} \\
+% \} \\
+% \end{syntax}
+%
+% Only for attributes of type |clist| or |date|. Set the separator between
+% items. If the argument is an one-item comma list, all separators are set to
+% \meta{separator} but \meta{separator before year} and \meta{separator after
+% day} is set empty.
+% \end{option}
+%
+% If the argument is a comma list of 3 items, it is used to set the separator
+% between items of the comma list. Following documentation is quoted from
+% \pkg{interface3}:
+% \begin{quote}
+% If the comma list has more than two items, the \meta{separator between
+% more than two} is placed between each pair of items except the last, for
+% which the \meta{separator between final two} is used. If the comma list
+% has exactly two items, then they are placed in the input stream separated
+% by the \meta{separator between two}. If the comma list has a single item,
+% it is placed in the input stream, and a comma list with no items produces
+% no output.
+% \end{quote}
+% For attributes of type |clist|, incorrect number (numbers exclude 1 and 3)
+% of items of the argument will raise an error. Example \ref{en-clist-sep}
+% shows how to use this option to customize the separators between comma
+% list items.
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(clist-sep){Set Separator Between Items of Comma List}
+ \dbNewDatabase{clist-db}{label=clist}
+ \dbNewStyle{clist-base}{clist-db}{
+ before-code = {\dbIfEmptyF{\begin{enumerate}}},
+ after-code = {\dbIfEmptyF{\end{enumerate}}},
+ item-code = \item \dbuse{label},
+ }
+ \dbNewStyle[clist-base]{clist-style1}{clist-db}{
+ label/sep = {{,~}}
+ }
+ \dbNewStyle[clist-base]{clist-style2}{clist-db}{
+ label/sep = {{,~}, {,~}, ~and~}
+ }
+ \dbitemkv{clist-db}{label={a, b, c}}
+ \dbitemkv{clist-db}{label={1, 2, 3}}
+ \dbshow{clist-style1}{clist-db}
+ \dbshow{clist-style2}{clist-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% If the argument is a comma list of 4 items, it is used to set the separators
+% of the date. For attributes of type |date|, incorrect number (numbers
+% exclude 1 and 4) will raise an error. Example \ref{en-date-sep} shows how
+% to customize the date separators.
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(date-sep){Set Date Separators}
+ \dbNewDatabase{date-db}{date=date}
+ \dbNewStyle{date-style1}{date-db}{
+ item-code = \dbuse{date}\quad,
+ date/sep = -,
+ }
+ \dbNewStyle{date-style2}{date-db}{
+ item-code = \dbuse{date}\quad,
+ date/sep = {\$, +, !, \$},
+ }
+ \dbitemkv{date-db}{date=2020/01/02}
+ \dbitemkv{date-db}{date=2022/07/12}
+ \dbshow{date-style1}{date-db}
+ \dbshow{date-style2}{date-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-14}{Add option}{\opt{<attr>/format-code}}
+% \begin{option}[added=2022-01-14, rEXP]{<attr>/format-code}
+% \begin{syntax}
+% \nopt{<attr>/format-code} = <format code> \inidef
+% \end{syntax}
+%
+% Use this option to get fine-grained control over date formatting. In
+% \meta{format code}, |#1| represents for the \meta{year}, |#2| represents for
+% the \meta{month} and |#3| represents for the \meta{day}. Example
+% \ref{en-date-code} shows how to format the date with this option.
+% \end{option}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(date-code){Date Formatting}
+ \dbNewDatabase{date-db}{date=date}
+ \dbNewStyle{date-style}{date-db}{
+ item-code = \dbuse{date},
+ date/format-code = {日:#3\quad 月:#2\quad 年:#1}
+ }
+ \dbitemkv{date-db}{date=2022/01/01}
+ \dbshow{date-style}{date-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}}
+% \begin{option}[added=2022-01-08, EXP]{<attr>/zfill}
+% \begin{syntax}
+% \nopt{<attr>/zfill} = <\TTF> \inidef(true)[true]
+% \end{syntax}
+%
+% Only for attributes of type |date|. Control whether to fill zero on the left
+% of the month or day. Example \ref{en-date-zfill} shows the differences.
+% \end{option}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(date-zfill){Control the Leading Zero of the Date}
+ \dbNewDatabase{date-db}{date=date}
+ \dbNewStyle {zfill-style}{date-db}{
+ item-code = \dbuse{date},
+ }
+ \dbNewStyle{nofill-style}{date-db}{
+ item-code = \dbuse{date},
+ date/zfill = false,
+ }
+ \dbitemkv{date-db}{date=2022/01/01}
+ \dbshow {zfill-style}{date-db}
+ \dbshow{nofill-style}{date-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbdatesep}}
+% \begin{function}[added=2022-01-13]{\dbdatesep}
+% \begin{syntax}
+% \cs{dbdatesep} \marg{separator}
+% \end{syntax}
+%
+% Set the separator for internal date parsing. The default value is |/|,
+% i.e. the date must be store in the format of |yyyy/mm/dd|. Example
+% \ref{en-inner-date-sep} shows how to store dates with two formats.
+% However, the separators are not really stored but used to parse the year,
+% month and day, which will be stored internally as three integers.
+% \end{function}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(inner-date-sep){Set Date Parsing Format}
+ \dbNewDatabase{inner-date-db}{date=date}
+ \dbNewStyle{inner-date-style}{inner-date-db}{
+ item-code = \dbuse{date}\quad,
+ }
+ \dbitemkv{inner-date-db}{date=2020/01/20}
+ \dbdatesep{-}
+ \dbitemkv{inner-date-db}{date=2022-01-10}
+ \dbshow{inner-date-style}{inner-date-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \subsection{Data Filters}
+%
+% Filter is a combination of conditionals that is used to filter the data you
+% want to display.
%
% \begin{function}[added=2022-01-05]{\dbNewReviewPoints}
% \begin{syntax}
% \cs{dbNewReviewPoints} \marg{name} \marg{points}
% \end{syntax}
%
-% Define the new \meta{points} that is specially designed for reviewing
-% something. \meta{points} is a list of integers. Suppose you record the date
-% when you did not answer correctly and you plan to review every 2, 5 and 15
-% days. The following code give what you want.
+% Define \meta{points} to filter dates by intervals. something. \meta{points}
+% is a list of \meta{intexpr}. In example \ref{en-review-points}, a \meta{date
+% anchor} and a list of \meta{points} is defined. During the filtering process,
+% \meta{interval} is calculated by $\meta{interval} = \meta{date anchor} -
+% \meta{date cmp}$, \meta{date cmp} is the \meta{date} of current item. Then
+% each \meta{intexpr} in \meta{points} is compared with \meta{interval} to
+% test if they are equal.
% \end{function}
%
-% \begin{verbatim}
-% \dbNewReviewPoints{review-point}{2, 5, 15} % define points
-% \begin{dbFilters}
-% \dbNewConditional{cond1}{date}{review-point|\Today} % define conditional
-% \dbCombineConditionals{filter1}{cond1} % define filter
-% \end{dbFilters}
-% \dbNewStyle{review-style}{ques}{filter=filter1} % define style
-% \end{verbatim}
-%
-% \subsection{Define Filters inside \env{dbFilters} Environment}
+% \iffalse
+%<*verb>
+% \fi
+\DeleteShortVerb{\|}
+\dbdatesep{/}
+\begin{example*}(review-points){Filter with Review Points}
+ \dbNewDatabase{filter-db}{date=date}
+ \dbNewReviewPoints{review}{2, 5}
+ \dbNewRawFilter*{review-filter}{filter-db}{date}{review|2022/02/06}
+ \dbNewStyle{filter-style}{filter-db}{
+ item-code = \dbuse{date}\quad,
+ filter = review-filter,
+ }
+ \dbitemkv{filter-db}{date=2022/01/30}
+ \dbitemkv{filter-db}{date=2022/02/01}
+ \dbitemkv{filter-db}{date=2022/02/04}
+ \dbshow{filter-style}{filter-db}
+\end{example*}
+\MakeShortVerb{\|}
+% \iffalse
+%</verb>
+% \fi
%
-% \begin{environment}[added=2022-01-05]{dbFilters}
+% \changes{1.5}{2022-01-16}{Update env}{add starred version of \env{dbFilters}}
+% \begin{environment}[added=2022-01-05, updated=2022-01-16]{dbFilters}
% \begin{syntax}
-% |\begin{dbFilters}|\marg{database} \\
+% |\begin|\{\env{dbFilters}\} \marg{database} \\
+% ~~\meta{code}
+% |\end|\{\env{dbFilters}\} \\
+% |\begin|\{\env{dbFilters}\} * \marg{database} \\
% ~~\meta{code}
-% |\end{dbFilters}| \\
+% |\end|\{\env{dbFilters}\} \\
% \end{syntax}
%
% Filters are defined inside \env{dbFilters} environment, inside which,
% \cs{dbNewConditional} is defined to declare conditionals and
-% \cs{dbCombineConditionals} is defined to combine conditionals. Filters are
-% independent in different databases, which means the same name of filters is
-% allowed in different databases.
+% \cs{dbCombineConditionals} is defined to combine conditionals. Starred
+% version will define a filter of the same name of conditional as soon as you
+% define it. In example \ref{en-star-filter}, line 3 define the conditional
+% and the filter named |greater| so that you can use it in option \opt{option}.
+% Filters are independent in different databases, which means the same name of
+% filters is allowed in different databases.
% \end{environment}
%
-% \begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(star-filter){Define Conditional and Filter at Same Time}
+ \dbNewDatabase{filter-db}{count=int}
+ \begin{dbFilters}*{filter-db}
+ \dbNewCond{greater}{count}{\dbval > 3}
+ \end{dbFilters}
+ \dbNewStyle{filter-style}{filter-db}{
+ filter = greater,
+ item-code = \dbuse{count}\quad,
+ }
+ \dbitemkv{filter-db}{count=2}
+ \dbitemkv{filter-db}{count=5}
+ \dbshow{filter-style}{filter-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-15}{Add macros}{\cs{dbNewCond}, \cs{dbCombCond}}
+% \begin{function}[added=2022-01-05, updated=2022-01-16]{\dbNewConditional,
+% \dbNewCond, \dbNewConditional*, \dbNewCond*}
% \begin{syntax}
-% \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \\
-% \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \\[2pt]
-% \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \\
-% \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \\
-% \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \\
-% \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \\
-% \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \\
-% \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \\
-% \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr}
-% \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\
+% \cs{dbNewConditional} \marg{name} \marg{attr} \marg{cond spec} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{attr} \marg{cond spec} \oarg{filter info} \\[2pt]
+% \cs{dbNewConditional} \marg{name} \marg{int/fp attr} \marg{expr} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{expr} \oarg{filter info}
+% \cs{dbNewConditional} \marg{name} \marg{str/tl attr} \marg{regex expr} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{str/tl attr} \marg{regex expr} \oarg{filter info}
+% \cs{dbNewConditional} \marg{name} \marg{clist attr} \marg{val list} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{clist attr} \marg{val list} \oarg{filter info}
+% \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{date expr} \oarg{filter info}
+% \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \oarg{filter info}
% \end{syntax}
%
% Define the conditional named \meta{name} that binds to \meta{attr}. \cs{dbval}
@@ -1557,53 +2693,176 @@ Copyright and License
% \end{note}
%
% For attribute of type |str| and |tl|, unstarred form matches any part while
-% starred form matches the whole part with the \meta{regex expr}.
+% starred form matches the whole part with the \meta{regex expr}, which is
+% shown in example \ref{en-filter-str}: filter |part| match |name|s that
+% contain numbers and filter |all| match |name|s that is composed of digits.
%
-% \begin{verbatim}
-% \dbNewConditional {cond1}{str-attr}{abc} % match abc, abcd, 1abc, =abc=, etc
-% \dbNewConditional*{cond2}{str-attr}{abc} % only match abc
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(filter-str){Match Strings}
+ \dbNewDatabase{filter-db}{name=str}
+ \begin{dbFilters}*{filter-db}
+ \dbNewCond{part}{name}{\d+}
+ \dbNewCond*{all}{name}{\d+}
+ \end{dbFilters}
+ \dbNewStyle{part-style}{filter-db}{
+ before-code = Match part:~,
+ item-code = \dbuse{name}\quad,
+ filter = part,
+ }
+ \dbNewStyle{all-style}{filter-db}{
+ before-code = Match all:~,
+ item-code = \dbuse{name}\quad,
+ filter = all,
+ }
+ \dbitemkv{filter-db}{name=123}
+ \dbitemkv{filter-db}{name=int12}
+ \dbitemkv{filter-db}{name=variable}
+ \dbshow{part-style}{filter-db}
+ \dbshow {all-style}{filter-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
%
% For attributes of type |clist|, the conditional defined by unstarred form is
% true if any item of \meta{val list} is in the comma list. While the
% conditional defined by starred form is true only if every item of \meta{val
-% list} is in the comma list. As is showed below, for |cond1|, |a| is in
-% |{a, b, d}| so |cond1| is true. While |c| is not in |{a, b, d}| so |cond2|
-% is false.
+% list} is in the comma list. In example \ref{en-filter-clist}, filter |or|
+% match labels that contain hard \textbf{or} red, and filter |and| match
+% labels that contain hard \textbf{and} red.
%
-% \begin{verbatim}
-% \dbNewConditional {cond1}{clist-attr}{a, b, c} % {a, b, d} -> true
-% \dbNewConditional*{cond2}{clist-attr}{a, b, c} % {a, b, d} -> false
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(filter-clist){Filter Lists}
+ \dbNewDatabase{filter-db}{label=clist}
+ \begin{dbFilters}*{filter-db}
+ \dbNewCond {or}{label}{hard, red}
+ \dbNewCond*{and}{label}{hard, red}
+ \end{dbFilters}
+ \def\emph#1{\textit{\textbf{#1}}}
+ \dbNewStyle{base-style}{filter-db}{
+ before-code = {
+ \begin{minipage}[t]{.3\textwidth}
+ All items
+ },
+ after-code = {\end{minipage}},
+ item-code = \par\dbarabic.~\dbuse{label},
+ }
+ \dbNewStyle[base-style] {or-style}{filter-db}{
+ before-code = {
+ \begin{minipage}[t]{.3\textwidth}
+ Match \emph{any} of hard \emph{or} red
+ },
+ filter = or,
+ }
+ \dbNewStyle[base-style]{and-style}{filter-db}{
+ before-code = {
+ \begin{minipage}[t]{.3\textwidth}
+ Match \emph{all} of hard \emph{and} red
+ },
+ filter = and,
+ }
+ \dbitemkv{filter-db}{label={hard, red}}
+ \dbitemkv{filter-db}{label={hard, blue}}
+ \dbitemkv{filter-db}{label={easy, blue}}
+ \dbitemkv{filter-db}{label={easy, red}}
+ \dbitemkv{filter-db}{label={hard, red, flat}}
+ \dbshow {base-style}{filter-db}
+ \dbshow {or-style}{filter-db}
+ \dbshow {and-style}{filter-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.3}{2022-01-08}{Update logic}{swap definition of starred and
% unstarred conditionals of date}
% For attributes of type |date|, unstarred form replace each date with a
-% integer representing for the days between \meta{date} and
-% \textit{1971/01/01}, and the result is passed to \cs{int_compare:nTF}.
+% integer representing for the days between \meta{date} and 1971/01/01, and
+% the result is passed to \cs{int_compare:nTF}. Example \ref{en-filter-date}
+% shows how to use the \meta{date expr} to filter the data.
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(filter-date){Filter with Date Expression}
+ \dbNewDatabase{filter-db}{date=date}
+ \dbNewRawFilter{date-filter}{filter-db}{date}{\dbval >= 2022/02/01}
+ \dbNewStyle{filter-style}{filter-db}{
+ item-code = \dbuse{date}\quad,
+ filter = date-filter,
+ }
+ \dbitemkv{filter-db}{date=2022/01/30}
+ \dbitemkv{filter-db}{date=2022/02/01}
+ \dbitemkv{filter-db}{date=2022/02/04}
+ \dbshow{filter-style}{filter-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
% Starred form defines the conditional with review points defined by
-% \cs{dbNewRdbNewReviewPoints} and \meta{date} is the date to be compared.
+% \cs{dbNewReviewPoints} and \meta{date} is the date to be compared (see
+% example \ref{en-review-points}).
+%
+% \changes{1.5}{2022-01-16}{Add macro}{\cs{dbNewRawFilter}}
+% \begin{function}[added=2022-01-16]{\dbNewRawFilter}
+% \begin{syntax}
+% \cs{dbNewRawFilter} \marg{name} \marg{database} \marg{attr} \marg{cond spec} \oarg{filter info}
+% \cs{dbNewRawFilter}* \marg{name} \marg{database} \marg{attr} \marg{cond spec} \oarg{filter info}
+% \textnormal{\textit{Equal to}}
+% |\begin|\{\env{dbFilters}\}*\phantom{\marg{name}}\marg{database}
+% ~~\cs{dbNewCond} \marg{name} \phantom{\marg{database}} \marg{attr} \marg{cond spec} \oarg{filter info}
+% ~~\cs{dbNewCond}* \marg{name} \phantom{\marg{database}} \marg{attr} \marg{cond spec} \oarg{filter info}
+% |\end|\{\env{dbFilters}\}
+% \end{syntax}
+%
+% Use this command to quickly define a \meta{filter} that has the same name
+% with the \meta{conditional}. Example \ref{en-new-raw-filter} is actually the
+% same with example \ref{en-star-filter}, but it is more concise.
+% \end{function}
+%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(new-raw-filter){Define Conditional and Filter at Same Time}
+ \dbNewDatabase{filter-db}{count=int}
+ \dbNewRawFilter{greater}{filter-db}{count}{\dbval > 3}
+ \dbNewStyle{filter-style}{filter-db}{
+ filter = greater,
+ item-code = \dbuse{count}\quad,
+ }
+ \dbitemkv{filter-db}{count=2}
+ \dbitemkv{filter-db}{count=5}
+ \dbshow{filter-style}{filter-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
%
% \begin{function}[added=2022-01-05]{\dbCombineConditionals}
% \begin{syntax}
% \cs{dbCombineConditionals} \marg{name} \marg{cond combination} \oarg{info}
% \end{syntax}
%
-% Define the filter \meta{name}, which combine the conditionals and store the
-% extra \meta{info} into \cs{dbFilterInfo}. So you can write something as\\
-% \verb=\dbCombineConditionals{filter}{(cond1 && cond2) || !cond3}=.\\
-% Supported operators are \verb=&&, ||, !=. You can set the option \opt{filter}
-% to \meta{name} to apply the filter when you display the database.
+% Define the filter \meta{name}, which combine the conditionals and store
+% the extra \meta{info} into \cs{dbFilterInfo}. Supported operators are
+% \verb=&&, ||, !=. You can set the option \opt{filter} to \meta{name} to
+% apply the filter when you display the database. See example
+% \ref{en-filter}.
% \end{function}
%
-% \subsection{Store Data with \env{dbitem} Environment}
+% \subsection{Store and Use Data}
%
% \changes{1.4}{2022-01-13}{Update env}{dbitem}
% \begin{environment}[added=2022-01-05, updated=2022-01-13]{dbitem}
% \begin{syntax}
-% |\begin{dbitem}| \marg{database} \oarg{attr-val list}
+% |\begin|\marg{\env{dbitem}} \marg{database} \oarg{attr-val list}
% ~~\meta{code} \\
-% |\end{dbitem}|
+% |\end|\marg{\env{dbitem}}
% \end{syntax}
%
% The data are stored with \env{dbitem} environment in two ways. Short data
@@ -1612,15 +2871,37 @@ Copyright and License
% \meta{attr} = \meta{val} is equal to \cs{dbsave}\marg{attr}\marg{val}, and
% \meta{attr} = \meta{val} is equal to \cs{dbsave*}\marg{attr}\marg{val},
% in which case, data will not be expanded in an |e| or |x|-type argument.
-% An example code is showned below.
+% Example \ref{en-dbitem} shows how to store data with \env{dbitem}.
% \end{environment}
%
-% \begin{verbatim}
-% \begin{dbitem}[date=2022-01-01, info=test]
-% \dbsave{question}{This is a test question.}
-% \dbsave{answer} {This is a test answer.}
-% \end{dbitem}
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example*}(dbitem){Store Date}
+ \dbNewDatabase{ques-db}{date=date, ques=tl, ans=tl}
+ \dbNewStyle{ques-style}{ques-db}{
+ item-code = {%
+ \par\dbuse{date}
+ \par\dbarabic.~\dbuse{ques}
+ \par\textbf{Answer:}~\dbuse{ans}
+ },
+ item-after-code = \medskip,
+ }
+ \begin{dbitem}{ques-db}[date=2022/01/01]
+ \dbsave{ques}{Distance from earth to moon?}
+ \dbsave{ans} {384,401 kilometers.}
+ \end{dbitem}
+ \begin{dbitem}{ques-db}[date=2022/01/02]
+ \dbsave{ques}{The number of English letters?}
+ \dbsave{ans} {26.}
+ \end{dbitem}
+ \dbshow{ques-style}{ques-db}
+\end{example*}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.4}{2022-01-13}{Add macro}{\cs{dbitemkv}}
% \begin{function}[added=2022-01-13]{\dbitemkv}
@@ -1653,7 +2934,8 @@ Copyright and License
% \end{syntax}
%
% Display the value of \meta{attr} of current record. \cs{dbuse} is
-% \textbf{expandable} and can be only used inside the option \opt{item-code}.
+% \textbf{expandable} and can be only used inside the option \opt{item-code},
+% \opt{item-before-code}, \opt{item-after-code}.
% \end{function}
%
% \subsection{Conditionals}
@@ -1661,21 +2943,71 @@ Copyright and License
% \begin{function}[added=2022-01-05, EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF}
% \begin{syntax}
% \cs{dbIfEmptyTF} \marg{true code} \marg{false code} \\
-% \cs{dbIfEmptyT} \marg{true code} \\
+% \cs{dbIfEmptyT} \marg{true code} \\
% \cs{dbIfEmptyF} \marg{false code}
% \end{syntax}
%
-% Test if the database is empty. The example below shows how to avoid an empty
-% list environment.
+% Test if the database is empty. Example \ref{en-empty-db} shows how to
+% avoid an empty list environment.
% \end{function}
%
-% \begin{verbatim}
-% \dbNewStyle{style-cond1}{database-test}{
-% before-code = {\dbIfEmptyF{\begin{enumerate}}},
-% after-code = {\dbIfEmptyF{\end{enumerate}}},
-% item-code = {\item \dbuse{attr-test}}
-% }
-% \end{verbatim}
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(empty-db){Avoid Empty List Environment}
+ \dbNewDatabase{test-db}{text=tl}
+ \dbNewRawFilter{alph}{test-db}{text}{\d}
+ \dbNewStyle{base-style}{test-db}{
+ before-code = \dbIfEmptyTF{Empty db}{\begin{enumerate}},
+ after-code = \dbIfEmptyF{\end{enumerate}}\medskip,
+ item-code = \item \dbuse{text},
+ }
+ \dbNewStyle[base-style]{empty-style}{test-db}{
+ raw-filter=!alph
+ }
+ \dbitemkv{test-db}{text={$1 + 1 = 2$.}}
+ \dbitemkv{test-db}{text={I have 2 pens.}}
+ \dbshow {base-style}{test-db}
+ \dbshow{empty-style}{test-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
+% \changes{1.5}{2022-01-17}{Add macros}{\cs{dbIfLastT}, \cs{dbIfLastF},
+% \cs{dbIfLastTF}}
+% \begin{function}[added=2022-01-17, EXP]{\dbIfLastT, \dbIfLastF, \dbIfLastTF}
+% \begin{syntax}
+% \cs{dbIfLastTF} \marg{true code} \marg{false code}
+% \cs{dbIfLastT} \marg{true code}
+% \cs{dbIfLastF} \marg{false code}
+% \end{syntax}
+%
+% Test if the current item is the last item to display. Example \ref{en-last}
+% shows how to set the separator between items.
+% \end{function}
+%
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example*}(last){Separator between Items}
+ \dbNewDatabase{last-db}{text=tl}
+ \dbNewStyle{last-style}{last-db}{
+ item-code = {%
+ \par\dbuse{text}\par%
+ \dbIfLastF{\textcolor{red}{\hrulefill separator\hrulefill}}%
+ },
+ }
+ \dbitemkv{last-db}{text=This is the first paragraph.}
+ \dbitemkv{last-db}{text=This is the second paragraph.}
+ \dbitemkv{last-db}{text=This is the last paragraph.}
+ \dbshow{last-style}{last-db}
+\end{example*}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}}
%
@@ -1687,26 +3019,50 @@ Copyright and License
% \dbIntMin, \dbIntMod, \dbFpSign,
% }
% \begin{syntax}
-% \cs{dbIntAbs} \Arg{intexpr}
-% \cs{dbIntSign} \Arg{intexpr}
-% \cs{dbIntDivRound} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntDivTruncate} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntMax} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntMin} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbIntMod} \Arg{intexpr_1} \marg{intexpr_2}
-% \cs{dbFpSign} \Arg{fpexpr}
-% \end{syntax}
-% \cs{dbIntAbs} is identical to \cs{int_abs:n} \\
-% \cs{dbIntSign} is identical to \cs{int_sign:n} \\
-% \cs{dbIntDivRound} is identical to \cs{int_div_round:nn} \\
-% \cs{dbIntDivTruncate} is identical to \cs{int_div_truncate:nn} \\
-% \cs{dbIntMax} is identical to \cs{int_max:nn} \\
-% \cs{dbIntMin} is identical to \cs{int_min:nn} \\
-% \cs{dbIntMod} is identical to \cs{int_mod:nn} \\
-% \cs{dbFpSign} is identical to \cs{fp_sign:n} \\
-% Detailed documentation see \pkg{interface3} \\
+% \cs{dbIntAbs} \Arg{intexpr}
+% \cs{dbIntSign} \Arg{intexpr}
+% \cs{dbIntDivRound} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntDivTruncate} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntMax} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntMin} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbIntMod} \Arg{intexpr_1} \Arg{intexpr_2}
+% \cs{dbFpSign} \Arg{fpexpr}
+% \end{syntax}
+% \begin{tblr}{ll}
+% \cs{dbIntAbs} & is equal to \cs{int_abs:n} \\
+% \cs{dbIntSign} & is equal to \cs{int_sign:n} \\
+% \cs{dbIntDivRound} & is equal to \cs{int_div_round:nn} \\
+% \cs{dbIntDivTruncate} & is equal to \cs{int_div_truncate:nn} \\
+% \cs{dbIntMax} & is equal to \cs{int_max:nn} \\
+% \cs{dbIntMin} & is equal to \cs{int_min:nn} \\
+% \cs{dbIntMod} & is equal to \cs{int_mod:nn} \\
+% \cs{dbFpSign} & is equal to \cs{fp_sign:n} \\
+% \end{tblr}
+%
+% See detailed documentation of \pkg{interface3}. Example \ref{en-expr-db}
+% shows how to filter multiples of 3.
% \end{function}
%
+% \iffalse
+%<*verb>
+% \fi
+\begin{example*}(expr-db){Filter Multiples of 3}
+ \dbNewDatabase{expr-db}{n=int}
+ \dbNewRawFilter{mod}{expr-db}{n}{\dbIntMod{\dbval}{3} = 0}
+ \dbNewStyle{expr-style}{expr-db}{
+ item-code = \dbuse{n}\quad,
+ filter = mod,
+ }
+ \dbitemkv{expr-db}{n=2}
+ \dbitemkv{expr-db}{n=3}
+ \dbitemkv{expr-db}{n=6}
+ \dbitemkv{expr-db}{n=7}
+ \dbshow{expr-style}{expr-db}
+\end{example*}
+% \iffalse
+%</verb>
+% \fi
+%
% \subsection{Special Macros}
%
% Some special macros are defined to expand to different contents according to context.
@@ -1721,208 +3077,60 @@ Copyright and License
% \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman
% }
% \begin{tblr}{ll}
-% \cs{dbval} & Attribute value, only according in \cs{dbNewConditional}. \\
-% \cs{dbDatabase} & Database name. \\
+% \cs{dbval} & Attribute value, only accessible in \cs{dbNewConditional}. \\
+% \cs{dbtoday} & Date of today. \\
+% \cs{dbDatabase} & Database name. \\
% \cs{dbFilterName} & Filter name. \\
% \cs{dbFilterInfo} & Filter information. \\
-% \cs{dbIndex} & Record index, identical to \cs{dbuse}|{id}| \\
-% \cs{dbarabic} & Show the counter of query set as digits. \\
-% \cs{dbalph} & Show the counter of query set as lowercase letters. \\
-% \cs{dbAlph} & Show the counter of query set as uppercase letters. \\
-% \cs{dbroman} & Show the counter of query set as lowercase roman numerals. \\
-% \cs{dbroman} & Show the counter of query set as uppercase roman numerals. \\
-% \end{tblr}
+% \cs{dbIndex} & Record index, identical to \cs{dbuse}\marg{id} \\
+% \cs{dbarabic} & Show the counter of query set as digits. \\
+% \cs{dbalph} & Show the counter of query set as lowercase letters. \\
+% \cs{dbAlph} & Show the counter of query set as uppercase letters. \\
+% \cs{dbroman} & Show the counter of query set as lowercase roman numerals. \\
+% \cs{dbroman} & Show the counter of query set as uppercase roman numerals. \\
+% \end{tblr}
+%
+% \cs{dbtoday} show the current date with the separator defined by
+% \cs{dbdatesep}. See example~\ref{en-special-cs}.
% \end{function}
%
-% \section{Example of Flaw Sweeper Template}
-% \label{sec:example}
+% \iffalse
+%<*verb>
+% \fi
+\MakePercentComment
+\begin{example*}(special-cs){Special Commands}
+ \dbNewDatabase{special-db}{name=str}
+ \dbNewRawFilter*{number}{special-db}{name}{\d+}[name that is a number]
+ \dbNewStyle{special-style}{special-db}{
+ before-code = {
+ Date: \dbtoday \\
+ Database: \dbDatabase
+ Filter: \dbFilterName \\
+ Filter info: \dbFilterInfo \par
+ \begin{tabular}{@{}lllllll}
+ Index & arabic & alph & Alph & roman & Roman & value \\
+ },
+ after-code = \end{tabular},
+ item-code* = {%
+ \dbIndex & \dbarabic & \dbalph & \dbAlph &
+ \dbroman & \dbRoman & \dbuse{name} \\
+ },
+ sort = name,
+ filter = number,
+ }
+ \dbitemkv{special-db}{name=test}
+ \dbitemkv{special-db}{name=12}
+ \dbitemkv{special-db}{name=int2}
+ \dbitemkv{special-db}{name=99}
+ \dbshow{special-style}{special-db}
+\end{example*}
+\MakePercentIgnore
+% \iffalse
+%</verb>
+% \fi
%
% \changes{1.1}{2022-01-07}{Update doc}{improve example}
-%
-% \begin{verbatim}
-% \documentclass{article}
-% \usepackage{amsmath, physics}
-% \usepackage{geometry}
-% \usepackage{dbshow}
-% \usepackage{tikz}
-% \usepackage{tcolorbox}
-% \tcbuselibrary{skins}
-% \usetikzlibrary{shadings}
-% \usepackage[hidelinks]{hyperref}
-%
-% \geometry{
-% margin=2cm
-% }
-%
-% % #1 link node #2 target node #3 text to show
-% \NewDocumentCommand \linktarget { m m m } {%
-% \hyperlink{#1}{#3}%
-% \raisebox{1em}{\hypertarget{#2}{}}%
-% }
-%
-% % question box
-% \tcbset{
-% base/.style={
-% empty,
-% frame engine=path,
-% colframe=yellow!10,
-% coltitle=red!70,
-% fonttitle=\bfseries\sffamily,
-% sharp corners,
-% left=4pt,
-% right=4pt,
-% drop fuzzy shadow,
-% drop fuzzy shadow,
-% borderline west={3pt}{-3pt}{red!80},
-% }
-% }
-%
-% \newtcolorbox{mybox}[1]{%
-% base, title = {#1}
-% }
-%
-% \dbNewReviewPoints{review}{1, 3, 7, 15, 30, 60}
-%
-% \dbNewDatabase{ques-book}{
-% ques = tl,
-% answer = tl,
-% count = int|1,
-% labels = clist,
-% date = date,
-% }
-%
-% \begin{dbFilters}{ques-book}
-% \dbNewConditional{hard}{labels}{hard}
-% \dbNewConditional{bad}{count}{\dbval > 1}
-% \dbNewConditional*{review}{date}{review|2022/01/07}
-% \dbNewConditional{after}{date}{\dbval > 2022/01/02}
-% \end{dbFilters}
-%
-% % show all questions with hyperlink to answers
-% \dbNewStyle{ques}{ques-book}{
-% before-code = {\section{Questions}},
-% item-code = {
-% \begin{mybox}{%
-% \linktarget{answer_\dbIndex}{ques_\dbIndex}{%
-% Question \dbarabic%
-% \hspace{2em}\dbuse{date}%
-% \hspace{2em}\dbuse{labels}%
-% \hfill\dbuse{count}%
-% }%
-% }
-% \dbuse{ques}%
-% \end{mybox}
-% },
-% labels/sep = /,
-% }
-%
-% % show all questions and answers with hyperlink to questions
-% \dbNewStyle{answer}{ques-book}{
-% before-code = {\section{Questions and Answers}},
-% item-code = {
-% \begin{mybox}{%
-% \linktarget{ques_\dbIndex}{answer_\dbIndex}{%
-% Question \dbarabic%
-% \hspace{2em}\dbuse{date}%
-% \hspace{2em}\dbuse{labels}%
-% \hfill\dbuse{count}%
-% }%
-% }
-% \dbuse{ques}\tcbsubtitle{Answer}\dbuse{answer}%
-% \end{mybox}
-% },
-% labels/sep = /,
-% }
-%
-% % show all hard questions with hyperlink to answers
-% \dbNewStyle{hard}{ques-book}{
-% before-code = {\section{Hard Questions}},
-% item-code = {
-% \begin{mybox}{%
-% \hyperlink{answer_\dbIndex}{%
-% Question \dbarabic%
-% \hspace{2em}\dbuse{date}%
-% \hspace{2em}\dbuse{labels}%
-% \hfill\dbuse{count}%
-% }%
-% }
-% \dbuse{ques}%
-% \end{mybox}
-% },
-% raw-filter = hard,
-% labels/sep = /,
-% }
-%
-% % show all hard questions that have been answered incorrectly for more than
-% % one time with hyperlink to answers
-% \dbNewStyle[hard]{bad}{ques-book}{
-% before-code = {\section{Bad Questions}},
-% raw-filter = {bad && hard},
-% }
-% % show all questions that plan to be reviewed on 2022/01/07 with hyperlink to
-% % answers
-% \dbNewStyle[hard]{review}{ques-book}{
-% before-code = {\section{Questions to be Reviewed}},
-% raw-filter = {review},
-% }
-% % show all questions that is record after 2022/01/02 with hyperlink to answers
-% \dbNewStyle[hard]{after}{ques-book}{
-% before-code = {\section{Questions after 2022/01/02}},
-% raw-filter = {after},
-% }
-%
-% \AtEndDocument{
-% \dbshow{review}{ques-book}
-% \dbshow{hard}{ques-book}
-% \dbshow{bad}{ques-book}
-% \dbshow{after}{ques-book}
-% \dbshow{ques}{ques-book}
-% \dbshow{answer}{ques-book}
-% }
-%
-% \begin{document}
-%
-% \begin{dbitem}{ques-book}[
-% date=2022/01/01,
-% labels={math, equation, easy},
-% count=2
-% ]
-% \dbsave{ques}{%
-% Solve the linear equation: $x + 16 = 31$.
-% }
-% \dbsave{answer}{%
-% $x = 31 - 16 = 15$
-% }
-% \end{dbitem}
-%
-% \begin{dbitem}{ques-book}[
-% date=2022/01/01,
-% labels={math, equation, hard},
-% count=3
-% ]
-% \dbsave{ques}{%
-% Solve the linear equation: $2y = 16$.
-% }
-% \dbsave{answer}{%
-% $y = 16 / 2 = 8$
-% }
-% \end{dbitem}
-%
-% \begin{dbitem}{ques-book}[
-% date=2022/01/04,
-% labels={math, integral, hard},
-% count=1
-% ]
-% \dbsave{ques}{%
-% Find the indefinite integral: $\int 2x \dd x$.
-% }
-% \dbsave{answer}{%
-% $\int 2x \dd x = x^2$
-% }
-% \end{dbitem}
-%
-% \end{document}
-% \end{verbatim}
+% \changes{1.5}{2022-01-17}{Remove doc}{Remove big example}
%
% \end{documentation}
%
@@ -1962,6 +3170,7 @@ Copyright and License
% \begin{macrocode}
\cs_generate_variant:Nn \msg_warning:nnnn { nnnx }
\cs_generate_variant:Nn \keys_set:nn { nv }
+\cs_generate_variant:Nn \tl_put_right:Nn { Nv }
\cs_generate_variant:Nn \clist_use:nn { xx }
\cs_generate_variant:Nn \clist_use:nnnn { xxxx }
\cs_generate_variant:Nn \clist_map_inline:nn { Vn }
@@ -2014,6 +3223,8 @@ Copyright and License
}
% \end{macrocode}
%
+% \changes{1.5}{2022-01-15}{Update check code}{transform arguments to string
+% before check}
% \begin{macro}{\@@_check_database:n}
% Check if the database is valid.
% \begin{arguments}
@@ -2021,7 +3232,7 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new:Nn \@@_check_database:n {
- \prop_if_exist:cF { g_@@_attr_type_prop_#1 }
+ \prop_if_exist:cF { g_@@_attr_type_prop_\tl_to_str:n {#1} }
{ \msg_fatal:nnn { dbshow } { non-existent-database } {#1} }
}
% \end{macrocode}
@@ -2045,7 +3256,7 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new:Nn \@@_check_attr:nn {
- \prop_if_in:cnF { g_@@_attr_type_prop_#1 } {#2}
+ \prop_if_in:cnF { g_@@_attr_type_prop_\tl_to_str:n {#1} } {#2}
{ \msg_fatal:nnnn { dbshow } { non-existent-attr } {#1} {#2} }
}
\cs_generate_variant:Nn \@@_check_attr:nn { nV }
@@ -2070,8 +3281,8 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new:Nn \@@_check_style:nn {
- \tl_if_exist:cF { g_@@_style_opts_tl_#1_#2 }
- { \msg_warning:nnnn { dbshow } { non-existent-style } {#1} {#2} }
+ \tl_if_exist:cF { g_@@_style_opts_tl_\tl_to_str:n {#1}_\tl_to_str:n {#2} }
+ { \msg_fatal:nnnn { dbshow } { non-existent-style } {#1} {#2} }
}
% \end{macrocode}
% \end{macro}
@@ -2094,7 +3305,7 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new:Nn \@@_check_cond:nnn {
- \tl_if_exist:cF { g_@@_filter_attr_#1_#2 }
+ \tl_if_exist:cF { g_@@_filter_attr_\tl_to_str:n {#1}_\tl_to_str:n {#2} }
{ \msg_fatal:nnnn { dbshow } { non-existent-cond } {#1} {#2} }
}
% \end{macrocode}
@@ -2118,7 +3329,8 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new:Nn \@@_check_filter:nn {
- \seq_if_exist:cF { g_@@_filter_run_seq_#1_#2 } {
+ \seq_if_exist:cF
+ { g_@@_filter_run_seq_\tl_to_str:n {#1}_\tl_to_str:n {#2} } {
\str_if_eq:eeF {#2} { -none- } {
\msg_warning:nnnx { dbshow } { non-existent-filter } {#1} {#2}
}
@@ -2163,7 +3375,7 @@ Copyright and License
}
% \end{macrocode}
%
-% \begin{macro}{\@@_sep_error:nnn, \@@_sep_error:xxx}
+% \begin{macro}{\@@_sep_fatal:nnn, \@@_sep_fatal:xxx}
% Check the value of \opt{<attr>/sep} is valid.
% \begin{arguments}
% \item \meta{valid count}
@@ -2171,10 +3383,10 @@ Copyright and License
% \item \meta{value}
% \end{arguments}
% \begin{macrocode}
-\cs_new:Nn \@@_sep_error:nnn {
- \msg_error:nnnnn { dbshow } { wrong-seperator } {#1} {#2} {#3}
+\cs_new:Nn \@@_sep_fatal:nnn {
+ \msg_fatal:nnnnn { dbshow } { wrong-seperator } {#1} {#2} {#3}
}
-\cs_generate_variant:Nn \@@_sep_error:nnn { xxx }
+\cs_generate_variant:Nn \@@_sep_fatal:nnn { xxx }
% \end{macrocode}
% \end{macro}
%
@@ -2190,9 +3402,11 @@ Copyright and License
%
% \subsection{Create Database}
%
+% \changes{1.5}{2022-01-15}{Fix bug}{can not use \cs{dbdatesep} midway}
% \begin{macro}{\@@_process_default_value:w}
% Create map from \meta{attr} to \meta{type} and map from \meta{attr} to
-% \meta{default value}.
+% \meta{default value}. Note that only one expansion is needed to get the
+% correct default value from \cs{l_@@_tmp_default}.
% \begin{arguments}
% \item \meta{database}
% \item \meta{attr}
@@ -2204,7 +3418,7 @@ Copyright and License
#1\@@_sep#2\@@_sep#3|#4\@@_stop {
\@@_check_type:n {#3}
\prop_gput:cxx { g_@@_attr_type_prop_#1 } {#2} {#3}
- \prop_gput:cxx { g_@@_default_map_#1 } {#2} {#4}
+ \prop_gput:cno { g_@@_default_map_#1 } {#2} {#4}
}
% \end{macrocode}
% \end{macro}
@@ -2617,7 +3831,7 @@ Copyright and License
% \begin{macro}{\@@_filter_tl:NNNnn, \@@_filter_tl:cccnn}
% Filter token list with regex expression. It is the same with string.
% \begin{macrocode}
-\cs_set_eq:NN \@@_filter_tl:NNNnn \@@_filter_str:NNNnn
+\cs_gset_eq:NN \@@_filter_tl:NNNnn \@@_filter_str:NNNnn
\cs_generate_variant:Nn \@@_filter_tl:NNNnn { cccnn }
% \end{macrocode}
% \end{macro}
@@ -2662,8 +3876,11 @@ Copyright and License
\__dbdate_set:xx { tmp_day1 } { \l_@@_filter_tmp_tl }
\__dbdate_set:xx { tmp_day2 } {#3}
\__dbdate_sub:nnN { tmp_day1 } { tmp_day2 } \l_@@_filter_diff_int
- \clist_if_in:NxTF \l_@@_filter_tmp_clist
- { \int_use:N \l_@@_filter_diff_int } {#4} {#5}
+ #5
+ \clist_map_inline:Nn \l_@@_filter_tmp_clist {
+ \int_compare:nNnT { \l_@@_filter_diff_int } = {##1}
+ { #4 \clist_map_break: }
+ }
} {
% \end{macrocode}
% For unstarred \meta{conditional} which parses \meta{expr}. We first replace
@@ -2711,11 +3928,12 @@ Copyright and License
% \item \meta{index}
% \end{arguments}
% \begin{macrocode}
-\cs_set:Nn \@@_filter:nnn {
+\cs_new_protected:Nn \@@_filter:nnn {
\tl_set_eq:Nc \l_@@_attr_tl { g_@@_filter_attr_tl_#1_#2 }
\cs_set_eq:Nc \dbval { g_@@_data_#1_\l_@@_attr_tl _#3 }
+ \tl_set:Nx \l_@@_type_tl { \@@_get_type:nV {#1} \l_@@_attr_tl }
\use:c
- { @@_filter_\@@_get_type:nV {#1} \l_@@_attr_tl :cccnn }
+ { @@_filter_\l_@@_type_tl :cccnn }
{ g_@@_cond_star_bool_#1_#2 }
{ g_@@_filter_expr_tl_#1_#2 }
{ dbval }
@@ -2739,6 +3957,8 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Nn \@@_new_conditional:nnnnn {
+ \@@_check_database:n {#1}
+ \@@_check_attr:nn {#1} {#3}
\tl_gset:cn { g_@@_filter_attr_tl_#1_#2 } {#3}
\tl_gset:cn { g_@@_filter_expr_tl_#1_#2 } {#4}
\bool_if_exist:cF { g_@@_filter_bool_#1_#2 }
@@ -2757,7 +3977,10 @@ Copyright and License
\cs_gset:cn { g_@@_filter_hook_#1_#2:n } {
\@@_filter:nnn {#1} {#2} {##1}
}
- \seq_gput_right:cn { g_@@_cond_seq_#1 } {#2}
+ \bool_if_exist:cF { g_@@_cond_exist_bool_#1_#2 }
+ { \bool_set_false:c { g_@@_cond_exist_bool_#1_#2 } }
+ \bool_if:cF { g_@@_cond_exist_bool_#1_#2 }
+ { \seq_gput_right:cn { g_@@_cond_seq_#1 } {#2} }
}
% \end{macrocode}
% \end{macro}
@@ -2778,7 +4001,7 @@ Copyright and License
\cs_new_protected:Nn \@@_combine_conditional:nnn {
\tl_gset_eq:cN { g_@@_filter_bool_tl_#1_#2 } \c_true_bool
\seq_gclear_new:c { g_@@_filter_run_seq_#1_#2 }
- \regex_extract_all:nnN { \w+ } {#3} \l_@@_cond_seq
+ \regex_extract_all:nnN { [^!=&<>()\ ]+ } {#3} \l_@@_cond_seq
% \end{macrocode}
% \begin{arguments}[2]
% \item \meta{conditional}
@@ -2786,13 +4009,18 @@ Copyright and License
% \begin{macrocode}
\seq_map_inline:Nn \l_@@_cond_seq {
\seq_if_in:cnT { g_@@_cond_seq_#1 } {##1} {
- \seq_gput_right:cn { g_@@_filter_run_seq_#1_#2 }
+ \seq_if_in:cnF { g_@@_filter_run_seq_#1_#2 }
{ g_@@_filter_hook_#1_##1:n }
+ {
+ \seq_gput_right:cn { g_@@_filter_run_seq_#1_#2 }
+ { g_@@_filter_hook_#1_##1:n }
+ }
}
}
\tl_set:Nn \l_@@_cond_expr_tl {#3}
\regex_replace_all:nnN
- { \w+ } { \c{ g_@@_filter_bool_#1_\0 } }
+ { (\w|-|\d|\_)+ }
+ { \c{ g_@@_filter_bool_#1_\0 } }
\l_@@_cond_expr_tl
\tl_gset_eq:cN
{ g_@@_filter_bool_tl_#1_#2 } \l_@@_cond_expr_tl
@@ -2801,25 +4029,30 @@ Copyright and License
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{dbFilters, \dbNewConditional, \dbCombineConditionals}
+% \begin{macro}{dbFilters, \dbNewConditional, \dbNewCond,
+% \dbCombineConditionals, \dbCombCond}
% Environment to define conditionals and filters.
% \begin{arguments}
% \item \meta{database}
% \end{arguments}
% \begin{macrocode}
-\NewDocumentEnvironment { dbFilters } { m } {
- \seq_gclear_new:c { g_@@_cond_seq_#1 }
+\NewDocumentEnvironment { dbFilters } { s m } {
+ \seq_if_exist:cF { g_@@_cond_seq_#2 }
+ { \seq_new:c { g_@@_cond_seq_#2 } }
% \end{macrocode}
% \begin{arguments}[2]
% \item \meta{star}
-% \item \meta{conditional}
+% \item \meta{filter/conditional}
% \item \meta{attr}
% \item \meta{expr}
+% \item \meta{filter info}
% \end{arguments}
% \begin{macrocode}
- \DeclareDocumentCommand { \dbNewConditional } { s m m m } {
- \@@_new_conditional:nnnnn
- {#1} {##2} {##3} {##4} {##1}
+ \DeclareDocumentCommand { \dbNewConditional } { s m m m O{} } {
+ \@@_new_conditional:nnnnn {#2} {##2} {##3} {##4} {##1}
+ \IfValueT {#1} {
+ \dbCombCond{##2}{##2}[##5]
+ }
}
% \end{macrocode}
% \begin{arguments}[2]
@@ -2829,13 +4062,36 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\DeclareDocumentCommand { \dbCombineConditionals } { m m O{} } {
- \tl_gset:cn { g_@@_filter_info_tl_#1_##1 } {##3}
- \@@_combine_conditional:nnn {#1} {##1} {##2}
+ \tl_gset:cn { g_@@_filter_info_tl_#2_##1 } {##3}
+ \@@_combine_conditional:nnn {#2} {##1} {##2}
}
+ \cs_set_eq:NN \dbNewCond \dbNewConditional
+ \cs_set_eq:NN \dbCombCond \dbCombineConditionals
} {}
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\dbNewRawFilter, \dbNewRawFilter*}
+% Define filter with single conditional.
+% \begin{arguments}
+% \item \meta{star}
+% \item \meta{filter and conditional name}
+% \item \meta{database}
+% \item \meta{attr}
+% \item \meta{expr}
+% \item \meta{filter info}
+% \end{arguments}
+% \begin{macrocode}
+\DeclareDocumentCommand { \dbNewRawFilter } { s m m m m O{} } {
+ \seq_if_exist:cF { g_@@_cond_seq_#3 }
+ { \seq_new:c { g_@@_cond_seq_#3 } }
+ \@@_new_conditional:nnnnn {#3} {#2} {#4} {#5} {#1}
+ \tl_gset:cn { g_@@_filter_info_tl_#3_#2 } {#6}
+ \@@_combine_conditional:nnn {#3} {#2} {#2}
+}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\dbNewReviewPoints}
% User interface to define \meta{review points}.
% \begin{arguments}
@@ -2853,26 +4109,19 @@ Copyright and License
% \dbIntMax, \dbIntMin, \dbIntMod, \dbFpSign}
% Function aliases to support more operations of integer and floating points.
% \begin{macrocode}
-\cs_set_eq:NN \dbIntAbs \int_abs:n
-\cs_set_eq:NN \dbIntSign \int_sign:n
-\cs_set_eq:NN \dbIntDivRound \int_div_round:nn
-\cs_set_eq:NN \dbIntDivTruncate \int_div_truncate:nn
-\cs_set_eq:NN \dbIntMax \int_max:nn
-\cs_set_eq:NN \dbIntMin \int_min:nn
-\cs_set_eq:NN \dbIntMod \int_mod:nn
-\cs_set_eq:NN \dbFpSign \fp_sign:n
+\cs_gset_eq:NN \dbIntAbs \int_abs:n
+\cs_gset_eq:NN \dbIntSign \int_sign:n
+\cs_gset_eq:NN \dbIntDivRound \int_div_round:nn
+\cs_gset_eq:NN \dbIntDivTruncate \int_div_truncate:nn
+\cs_gset_eq:NN \dbIntMax \int_max:nn
+\cs_gset_eq:NN \dbIntMin \int_min:nn
+\cs_gset_eq:NN \dbIntMod \int_mod:nn
+\cs_gset_eq:NN \dbFpSign \fp_sign:n
% \end{macrocode}
% \end{macro}
%
% \subsection{Style and Options}
%
-% \begin{macro}{\@@_identity:n}
-% Does nothing and keep things unchanged.
-% \begin{macrocode}
-\cs_new:Nn \@@_identity:n {#1}
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}{\@@_new_attr_style:nnn}
% Define style keys for each attribute.
% \begin{arguments}
@@ -2892,6 +4141,15 @@ Copyright and License
g_@@_style_attr_after_tl_#1_#2_#3
},
after-code .initial:n = ,
+ code .code:n = {
+ \bool_gset_false:c { g_@@_style_attr_exp_bool_#1_#2_#3 }
+ \cs_gset:cn { @@_style_attr_code_#1_#2_#3:n } {##1}
+ },
+ code .initial:n = {##1},
+ code* .code:n = {
+ \bool_gset_true:c { g_@@_style_attr_exp_bool_#1_#2_#3 }
+ \cs_gset:cn { @@_style_attr_code_#1_#2_#3:n } {##1}
+ },
% \end{macrocode}
% For comma list and date.
% \begin{macrocode}
@@ -2909,18 +4167,28 @@ Copyright and License
g_@@_style_attr_item_after_tl_#1_#2_#3
},
item-after-code .initial:n = ,
+ item-code .code:n = {
+ \bool_gset_false:c { g_@@_style_clist_item_exp_bool_#1_#2_#3 }
+ \cs_gset:cn { @@_style_clist_item_code_#1_#2_#3:n } {##1}
+ },
+ item-code .initial:n = {##1},
+ item-code* .code:n = {
+ \bool_gset_true:c { g_@@_style_clist_item_exp_bool_#1_#2_#3 }
+ \cs_gset:cn { @@_style_clist_item_code_#1_#2_#3:n } {##1}
+ },
% \end{macrocode}
% Only for date.
% \begin{macrocode}
zfill .bool_gset:c = {
- g_@@_style_attr_zfill_bool_#1_#2_#3
+ g_@@_style_date_zfill_bool_#1_#2_#3
},
zfill .initial:n = true,
zfill .default:n = true,
- wrapper .tl_gset:c = {
- g_@@_style_attr_wrapper_#1_#2_#3
+ format-code .code:n = {
+ \cs_gset:cn { @@_style_date_format_code_#1_#2_#3:nnn } {##1}
+ \cs_generate_variant:cn
+ { @@_style_date_format_code_#1_#2_#3:nnn } { xxx }
},
- wrapper .initial:n = { \@@_identity:n },
}
\str_case_e:nn { \@@_get_type:nn {#2} {#3} } {
{ clist }
@@ -2947,21 +4215,28 @@ Copyright and License
\str_set:Nx \l_@@_raw_filter_str
{ -raw\int_use:N \g_@@_raw_filter_int - }
\tl_gset:cV { g_@@_filter_#1_#2 } \l_@@_raw_filter_str
- \@@_combine_conditional:nnn {#2} \l_@@_raw_filter_str {##1}
+ \@@_combine_conditional:nVn {#2} \l_@@_raw_filter_str {##1}
+ },
+ filter .tl_gset:c = { g_@@_filter_#1_#2 },
+ filter .initial:n = -none-,
+ sort .clist_gset:c = { g_@@_sort_clist_#1_#2 },
+ before-code .tl_gset:c = { g_@@_style_before_tl_#1_#2 },
+ before-code .initial:n = ,
+ after-code .tl_gset:c = { g_@@_style_after_tl_#1_#2 },
+ after-code .initial:n = ,
+ item-before-code .tl_gset:c = { g_@@_style_item_before_tl_#1_#2 },
+ item-before-code .initial:n = ,
+ item-after-code .tl_gset:c = { g_@@_style_item_after_tl_#1_#2 },
+ item-after-code .initial:n = ,
+ item-code .code:n = {
+ \bool_gset_false:c { g_@@_style_item_exp_bool_#1_#2 }
+ \tl_gset:cn { g_@@_style_item_tl_#1_#2 } {##1}
+ },
+ item-code .initial:n = ,
+ item-code* .code:n = {
+ \bool_gset_true:c { g_@@_style_item_exp_bool_#1_#2 }
+ \tl_gset:cn { g_@@_style_item_tl_#1_#2 } {##1}
},
- filter .tl_gset:c = { g_@@_filter_#1_#2 },
- filter .initial:n = -none-,
- sort .clist_gset:c = { g_@@_sort_clist_#1_#2 },
- before-code .tl_gset:c = { g_@@_style_before_tl_#1_#2 },
- before-code .initial:n = ,
- item-code .tl_gset:c = { g_@@_style_database_item_tl_#1_#2 },
- item-code .initial:n = ,
- after-code .tl_gset:c = { g_@@_style_after_tl_#1_#2 },
- after-code .initial:n = ,
- record-before-code .tl_gset:c = { g_@@_style_record_before_tl_#1_#2 },
- record-before-code .initial:n = ,
- record-after-code .tl_gset:c = { g_@@_style_record_after_tl_#1_#2 },
- record-after-code .initial:n = ,
}
\prop_map_inline:cn { g_@@_attr_type_prop_#2 }
{ \@@_new_attr_style:nnn {#1} {#2} {##1} }
@@ -2969,6 +4244,8 @@ Copyright and License
% \end{macrocode}
% \end{macro}
%
+% \changes{1.5}{2022-01-15}{Add check}{check if database is valid in
+% \cs{dbNewStyle}}
% \begin{macro}{\dbNewStyle}
% Set style options based on \meta{base style}.
% \begin{arguments}
@@ -2979,6 +4256,7 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\NewDocumentCommand { \dbNewStyle } { o m m +m } {
+ \@@_check_database:n {#3}
\tl_gset:cn { g_@@_style_opts_tl_#2_#3 } { #4, }
\IfValueT {#1} {
\tl_clear_new:N \l_@@_style_tmp_tl
@@ -3070,7 +4348,7 @@ Copyright and License
{ \@@_get_type:nV {#1} \l_@@_sort_attr_str }
\clist_if_in:nVF
{ str, int, date, fp } { \l_@@_sort_type_tl } {
- \msg_error:nnx { dbshow } { unsupported-sort-type }
+ \msg_fatal:nnx { dbshow } { unsupported-sort-type }
{ \l_@@_sort_type_tl }
}
\str_if_eq:eeT { \l_@@_sort_type_tl } { date }
@@ -3110,51 +4388,57 @@ Copyright and License
%
% \subsection{Display Data}
%
-% \begin{macro}{\@@_clist_wrapper:NNn}
+% \begin{macro}{\@@_clist_wrapper:NNNNn}
% Wrap the clist item with \meta{before code} and \meta{after code}.
% \begin{arguments}
% \item \meta{before code tl}
% \item \meta{after code tl}
+% \item \meta{item code cs}
+% \item \meta{exp boolean var}
% \item \meta{item}
% \end{arguments}
% \begin{macrocode}
-\cs_new:Nn \@@_clist_wrapper:NNn {
- \exp_not:n { { #1#3#2 }, }
+\cs_new:Nn \@@_clist_wrapper:NNNNn {
+ \bool_if:NTF #4
+ { \exp_not:n { { #1\exp_args:Nx#3{#5}#2 }, } }
+ { \exp_not:n { { #1#3{#5}#2 }, } }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@@_clist_use:NNNN, \@@_clist_use:cccc}
+% \begin{macro}{\@@_clist_use:NNNNNN, \@@_clist_use:cccccc}
% Display a comma list.
% \begin{arguments}
% \item \meta{data clist}
% \item \meta{separator clist}
% \item \meta{before code tl}
% \item \meta{after code tl}
+% \item \meta{item code cs}
+% \item \meta{exp boolean var}
% \end{arguments}
% \begin{macrocode}
-\cs_new:Nn \@@_clist_use:NNNN {
+\cs_new:Nn \@@_clist_use:NNNNNN {
\int_case:nnF { \clist_count:N #2 } {
{ 1 } {
\clist_use:xx
- { \clist_map_tokens:Nn #1 { \@@_clist_wrapper:NNn #3 #4 } }
+ { \clist_map_tokens:Nn #1 { \@@_clist_wrapper:NNNNn #3#4#5#6 } }
{ \clist_item:Nn #2 { 1 } }
}
{ 3 } {
\clist_use:xxxx
- { \clist_map_tokens:Nn #1 { \@@_clist_wrapper:NNn #3 #4 } }
+ { \clist_map_tokens:Nn #1 { \@@_clist_wrapper:NNNNn #3#4#5#6 } }
{ \clist_item:Nn #2 { 1 } }
{ \clist_item:Nn #2 { 2 } }
{ \clist_item:Nn #2 { 3 } }
}
} {
- \@@_sep_error:xxx
+ \@@_sep_fatal:xxx
{ 1~or~3 }
{ \clist_count:N #2 }
{ \clist_use:Nn #2 { ,~ } }
}
}
-\cs_generate_variant:Nn \@@_clist_use:NNNN { cccc }
+\cs_generate_variant:Nn \@@_clist_use:NNNNNN { cccccc }
% \end{macrocode}
% \end{macro}
%
@@ -3186,7 +4470,7 @@ Copyright and License
{ \clist_item:Nn #2 { 4 } }
}
} {
- \@@_sep_error:xxx
+ \@@_sep_fatal:xxx
{ 1~or~4 }
{ \clist_count:N #2 }
{ \clist_use:Nn #2 { ,~ } }
@@ -3196,8 +4480,9 @@ Copyright and License
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@@_use_data:nnnn}
-% Display Data.
+% \begin{macro}{\@@_use_data:nnnn, \@@_use_data_raw:nnnn}
+% Display Data. \cs{@@_use_data:nnnn} wrap the \meta{attr} data and
+% \cs{@@_use_data_raw:nnnn} display the underlying data.
% \begin{arguments}
% \item \meta{database}
% \item \meta{attr}
@@ -3205,26 +4490,40 @@ Copyright and License
% \item \meta{style}
% \end{arguments}
% \begin{macrocode}
-% #1 database #2 attr #3 index #4 style
\cs_new:Nn \@@_use_data:nnnn {
+ \bool_if:cTF { g_@@_style_attr_exp_bool_#4_#1_#2 } {
+ \protected@edef\@dbshow@tmp{\@@_use_data_raw:nnnn {#1} {#2} {#3} {#4}}
+ \exp_args:Nno
+ \use:c { @@_style_attr_code_#4_#1_#2:n } { \@dbshow@tmp }
+ } {
+ \use:c { @@_style_attr_code_#4_#1_#2:n }
+ { \@@_use_data_raw:nnnn {#1} {#2} {#3} {#4} }
+ }
+}
+\cs_new:Nn \@@_use_data_raw:nnnn {
\str_case_e:nn
{ \prop_item:cn { g_@@_attr_type_prop_#1 } {#2} } {
{ str } { \str_use:c { g_@@_data_#1_#2_#3 } }
- { tl } { \tl_use:c { g_@@_data_#1_#2_#3 } }
+ { tl } { \tl_use:c { g_@@_data_#1_#2_#3 } }
{ int } { \int_use:c { g_@@_data_#1_#2_#3 } }
- { fp } { \fp_use:c { g_@@_data_#1_#2_#3 } }
+ { fp } { \fp_use:c { g_@@_data_#1_#2_#3 } }
{ clist } {
- \@@_clist_use:cccc { g_@@_data_#1_#2_#3 }
+ \@@_clist_use:cccccc { g_@@_data_#1_#2_#3 }
{ g_@@_style_attr_sep_#4_#1_#2 }
{ g_@@_style_attr_item_before_tl_#4_#1_#2 }
- { g_@@_style_attr_item_after_tl_#4_#1_#2 }
+ { g_@@_style_attr_item_after_ tl_#4_#1_#2 }
+ { @@_style_clist_item_code_ #4_#1_#2:n }
+ { g_@@_style_clist_item_exp_bool_#4_#1_#2 }
}
{ date } {
- \exp_args:Nnx
- \tl_use:c { g_@@_style_attr_wrapper_#4_#1_#2 } {
+ \cs_if_exist_use:cTF { @@_style_date_format_code_#4_#1_#2:xxx } {
+ { \__dbdate_get_year:n { g_@@_data_#1_#2_#3 } }
+ { \__dbdate_get_month:n { g_@@_data_#1_#2_#3 } }
+ { \__dbdate_get_day:n { g_@@_data_#1_#2_#3 } }
+ } {
\@@_date_use:ncc { g_@@_data_#1_#2_#3 }
{ g_@@_style_attr_sep_#4_#1_#2 }
- { g_@@_style_attr_zfill_bool_#4_#1_#2 }
+ { g_@@_style_date_zfill_bool_#4_#1_#2 }
}
}
}
@@ -3247,7 +4546,7 @@ Copyright and License
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\@@_show_filter:nn}
+% \begin{macro}{\@@_show_filter:nnN}
% Filter records by executing the hook function in the running sequence and
% then testing the result boolean.
% \begin{arguments}
@@ -3289,11 +4588,31 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Nn \@@_show_set_counter:N {
- \tl_set:Nx \dbalph { \int_to_alph:n {#1} }
- \tl_set:Nx \dbAlph { \int_to_Alph:n {#1} }
+ \tl_set:Nx \dbalph { \int_to_alph:n {#1} }
+ \tl_set:Nx \dbAlph { \int_to_Alph:n {#1} }
\tl_set:Nx \dbarabic { \int_to_arabic:n {#1} }
- \tl_set:Nx \dbRoman { \int_to_Roman:n {#1} }
- \tl_set:Nx \dbroman { \int_to_roman:n {#1} }
+ \tl_set:Nx \dbRoman { \int_to_Roman:n {#1} }
+ \tl_set:Nx \dbroman { \int_to_roman:n {#1} }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_show_set_if_last:NN, \dbIfLastT, \dbIfLastF, \dbIfLastTF}
+% Define conditional to check if the current item is the last item.
+% \begin{arguments}
+% \item \meta{current index}
+% \item \meta{count}
+% \end{arguments}
+% \begin{macrocode}
+\cs_new_protected:Nn \@@_show_set_if_last:NN {
+ \prg_set_conditional:Nnn \@@_show_if_last: { T, F, TF } {
+ \int_compare:nNnTF {#1} = {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ \cs_set_eq:NN \dbIfLastT \@@_show_if_last:T
+ \cs_set_eq:NN \dbIfLastF \@@_show_if_last:F
+ \cs_set_eq:NN \dbIfLastTF \@@_show_if_last:TF
}
% \end{macrocode}
% \end{macro}
@@ -3308,6 +4627,9 @@ Copyright and License
% \begin{macrocode}
\cs_new_protected:Nn \@@_show_item:nnN {
\int_zero_new:N \l_@@_show_int
+ \int_zero_new:N \l_@@_show_count_int
+ \int_set:Nn \l_@@_show_count_int { \clist_count:N #3 }
+ \tl_clear_new:N \l_@@_item_tl
% \end{macrocode}
% \begin{arguments}[2]
% \item \meta{index}
@@ -3315,7 +4637,8 @@ Copyright and License
% \begin{macrocode}
\clist_map_inline:Nn #3 {
\int_incr:N \l_@@_show_int
- \@@_show_set_counter:N \l_@@_show_int
+ \@@_show_set_if_last:NN \l_@@_show_int \l_@@_show_count_int
+ \@@_show_set_counter:N \l_@@_show_int
\tl_set:Nn \dbIndex {##1}
% \end{macrocode}
% \begin{arguments}[3]
@@ -3326,12 +4649,21 @@ Copyright and License
\@@_check_attr:nn {#2} {####1}
\tl_use:c { g_@@_style_attr_before_tl_#1_#2_####1 }
\@@_use_data:nnnn {#2} {####1} {##1} {#1}
- \tl_use:c { g_@@_style_attr_after_tl_#1_#2_####1 }
+ \tl_use:c { g_@@_style_attr_after_ tl_#1_#2_####1 }
+ }
+ \bool_if:cTF { g_@@_style_item_exp_bool_#1_#2 } {
+ \protected@edef\@dbshow@tmp{\tl_use:c { g_@@_style_item_before_tl_#1_#2 }}
+ \tl_put_right:No \l_@@_item_tl { \@dbshow@tmp }
+ \protected@edef\@dbshow@tmp{\tl_use:c { g_@@_style_item_ tl_#1_#2 }}
+ \tl_put_right:No \l_@@_item_tl { \@dbshow@tmp }
+ \protected@edef\@dbshow@tmp{\tl_use:c { g_@@_style_item_after_ tl_#1_#2 }}
+ } {
+ \tl_use:c { g_@@_style_item_before_tl_#1_#2 }
+ \tl_use:c { g_@@_style_item_ tl_#1_#2 }
+ \tl_use:c { g_@@_style_item_after_ tl_#1_#2 }
}
- \tl_use:c { g_@@_style_record_before_tl_#1_#2 }
- \tl_use:c { g_@@_style_database_item_tl_#1_#2 }
- \tl_use:c { g_@@_style_record_after_tl_#1_#2 }
}
+ \l_@@_item_tl
}
% \end{macrocode}
% \end{macro}
@@ -3355,8 +4687,14 @@ Copyright and License
% \end{macrocode}
% \end{macro}
%
+% \changes{1.5}{2022-01-15}{Fix bug}{\cs{dbIfEmptyF} undefined}
% \begin{macro}{\@@_show:nnn, \@@_show:nnv}
% First filter records and sort them if needed and display at last.
+% \begin{arguments}
+% \item \meta{style}
+% \item \meta{database}
+% \item \meta{filter}
+% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Nn \@@_show:nnn {
\@@_show_set_macro:nn {#2} {#3}
@@ -3364,6 +4702,7 @@ Copyright and License
\@@_show_filter:nnN {#2} {#3} \l_@@_show_index_clist
\clist_if_empty:cF { g_@@_sort_clist_#1_#2 }
{ \@@_sort:nNn {#2} \l_@@_show_index_clist {#1} }
+ \@@_show_set_cond:N \l_@@_show_index_clist
\tl_use:c { g_@@_style_before_tl_#1_#2 }
\@@_show_item:nnN {#1} {#2} \l_@@_show_index_clist
\tl_use:c { g_@@_style_after_tl_#1_#2 }
@@ -3381,8 +4720,9 @@ Copyright and License
% \begin{macrocode}
\NewDocumentCommand { \dbshow } { m m } {
\@@_check_database:n {#2}
- \@@_check_filter:nv {#2} { g_@@_filter_#1_#2 }
- \@@_show:nnv {#1} {#2} { g_@@_filter_#1_#2 }
+ \@@_check_style:nn {#1} {#2}
+ \@@_check_filter:nv {#2} { g_@@_filter_#1_#2 }
+ \@@_show:nnv {#1} {#2} { g_@@_filter_#1_#2 }
}
% \end{macrocode}
% \end{macro}
@@ -3393,6 +4733,38 @@ Copyright and License
%<@@=dbdate>
% \end{macrocode}
%
+% \begin{arguments}
+% \item \meta{date}
+% \item \meta{date sep}
+% \end{arguments}
+% \begin{macrocode}
+\msg_new:nnn { dbshow } { wrong-date-sep } {
+ can~not~parse~the~date~'#1'~with~the~global~date~separator~'#2'~
+ \msg_line_context:.~Please~set~the~correct~date~separator~with~
+ \dbdatesep.
+}
+% \end{macrocode}
+%
+% \begin{macro}{\@@_check_date_sep:nn, \@@_check_date_sep:Vn}
+% Check if the global date separator is valid.
+% \begin{arguments}
+% \item \meta{date}
+% \item \meta{date sep}
+% \end{arguments}
+% \begin{macrocode}
+\cs_new:Nn \@@_check_date_sep:nn {
+ \int_zero_new:N \l_@@_sep_int
+ \tl_map_inline:nn {#1} {
+ \tl_if_eq:nnT {#2} {##1} { \int_incr:N \l_@@_sep_int }
+ \int_compare:nNnT { \l_@@_sep_int } > { 2 } { \tl_map_break: }
+ }
+ \int_compare:nNnF { \l_@@_sep_int } = { 2 }
+ { \msg_fatal:nnnn { dbshow } { wrong-date-sep } {#1} {#2} }
+}
+\cs_generate_variant:Nn \@@_check_date_sep:nn { nV }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[pTF]{\@@_if_leap:n}
% Check if the year is leap.
% \begin{arguments}
@@ -3563,6 +4935,28 @@ Copyright and License
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_get_year:n, \@@_get_year:x, \@@_get_month:n,
+% \@@_get_month:x, \@@_get_day:n, \@@_get_day:x}
+% Extract year, month or day from \meta{date var}.
+% \begin{arguments}
+% \item \meta{date var}
+% \end{arguments}
+% \begin{macrocode}
+\cs_new:Nn \@@_get_year:n {
+ \int_use:c { @@_year_#1 }
+}
+\cs_new:Nn \@@_get_month:n {
+ \int_use:c { @@_month_#1 }
+}
+\cs_new:Nn \@@_get_day:n {
+ \int_use:c { @@_day_#1 }
+}
+\cs_generate_variant:Nn \@@_get_year:n { x }
+\cs_generate_variant:Nn \@@_get_month:n { x }
+\cs_generate_variant:Nn \@@_get_day:n { x }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\@@_set:nnnn, \@@_gset:nnnn}
% Set the value of \meta{date var}.
% \begin{arguments}
@@ -3626,10 +5020,12 @@ Copyright and License
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Nn \@@_set:nn {
+ \@@_check_date_sep:nV {#2} \g_@@_sep_tl
\@@_set:w #1\@@_sep#2\@@_stop
}
\cs_generate_variant:Nn \@@_set:nn { xx }
\cs_new_protected:Nn \@@_gset:nn {
+ \@@_check_date_sep:nV {#2} \g_@@_sep_tl
\@@_gset:w #1\@@_sep#2\@@_stop
}
\cs_generate_variant:Nn \@@_gset:nn { xx }
diff --git a/macros/latex/contrib/dbshow/dbshow.pdf b/macros/latex/contrib/dbshow/dbshow.pdf
index 8d7c4d1bc2..7e3d14fb73 100644
--- a/macros/latex/contrib/dbshow/dbshow.pdf
+++ b/macros/latex/contrib/dbshow/dbshow.pdf
Binary files differ
diff --git a/macros/latex/contrib/easybook/easybook.dtx b/macros/latex/contrib/easybook/easybook.dtx
index ec8cfcee74..578d585706 100644
--- a/macros/latex/contrib/easybook/easybook.dtx
+++ b/macros/latex/contrib/easybook/easybook.dtx
@@ -15,7 +15,7 @@
%<*class>
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\RequirePackage{l3keys2e}
-\ProvidesExplClass{easybook}{2022/01/15}{1.46C}
+\ProvidesExplClass{easybook}{2022/01/16}{1.46E}
{Typeset Chinese theses or books}
\bool_set_false:N \l__eb_compile_draft_bool
@@ -305,7 +305,7 @@
%<*package>
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\RequirePackage{l3keys2e,etoolbox}
-\ProvidesExplPackage{easybase}{2022/01/15}{1.46C}
+\ProvidesExplPackage{easybase}{2022/01/16}{1.46E}
{Typeset Chinese theses or books}
\cs_generate_variant:Nn \dim_set:Nn { NV }
@@ -566,9 +566,9 @@
withpart .bool_set:N = \l__eb_chap_counter_withpart_bool,
withpart .default:n = true,
withpart .initial:n = false,
- uppercase .bool_set:N = \l__eb_mark_uppercase_bool,
- uppercase .default:n = true,
- uppercase .initial:n = true,
+ uppercase .tl_set:N = \l__eb_mark_uppercase_value_tl,
+ uppercase .default:n = all,
+ uppercase .initial:n = all,
brackets .code:n = \eb_assign_tag_brackets:n {#1},
brackets .initial:n = { (,) },
figurepath .tl_set:N = \l_eb_graphics_path_tl
@@ -654,14 +654,34 @@
\tl_if_novalue:nF {#5} { \vspace*{#5} }
\group_end:
}
+\cs_new:Npn \eb_mark_uppercase_case_init:n
+ {
+ \str_case:Vn \l__eb_mark_uppercase_value_tl
+ {
+ { all } { \text_uppercase:n }
+ { first } { \text_titlecase_first:n }
+ }
+ }
\ctex_define:nn { hdrset }
{
chap-mark .cs_set:Np = \eb_fancyhf_chapter_mark:n #1,
- chap-mark .initial:n = \CTEXifname{\eb@mark@chapter@label}{}#1,
+ chap-mark .initial:n =
+ {
+ \CTEXifname{\eb@mark@chapter@label}{}
+ \eb_mark_uppercase_case_init:n {#1}
+ },
sec-mark .cs_set:Np = \eb_fancyhf_section_mark:n #1,
- sec-mark .initial:n = \CTEXifname{\eb@mark@section@label}{}#1,
+ sec-mark .initial:n =
+ {
+ \CTEXifname{\eb@mark@section@label}{}
+ \eb_mark_uppercase_case_init:n {#1}
+ },
subsec-mark .cs_set:Np = \eb_fancyhf_subsection_mark:n #1,
- subsec-mark .initial:n = \CTEXifname{\eb@mark@subsection@label}{}#1,
+ subsec-mark .initial:n =
+ {
+ \CTEXifname{\eb@mark@subsection@label}{}
+ \eb_mark_uppercase_case_init:n {#1}
+ },
chap-label .code:n = \eb_mark_chapter_name_parse:n {#1},
chap-label .initial:n = \hspace{1em},
sec-label .code:n = \eb_mark_section_name_parse:n {#1},
@@ -680,20 +700,11 @@
footnoterule .initial:n = \markrule[0.35\textwidth]{\eb@footnote@rule@wd}[|3pt]
}
-\cs_set_eq:NN \eb_mark_uppercase:n \text_uppercase:n
-\cs_set_eq:NN \eb_mark_nouppercase:n \text_titlecase_first:n
-\cs_new:Npn \eb_mark_if_uppercase:nn #1#2
- {
- \bool_if:NTF \l__eb_mark_uppercase_bool
- { \eb_mark_uppercase:n }
- { \eb_mark_nouppercase:n }
- { \use:c { eb_fancyhf_#1_mark:n } {#2} }
- }
\cs_set:Npn \markdouble #1 { \markboth{#1}{\ifbool{@twoside}{#1}{}} }
\cs_new:Npn \eb@level@markdouble #1#2
- { \markdouble{\eb_mark_if_uppercase:nn {#1} {#2}} }
+ { \markdouble{\use:c { eb_fancyhf_#1_mark:n } {#2}} }
\cs_new:Npn \eb@level@markright #1#2
- { \markright{\eb_mark_if_uppercase:nn {#1} {#2}} }
+ { \markright{\use:c { eb_fancyhf_#1_mark:n } {#2}} }
\cs_gset:Npn \chaptermark #1 { \eb@level@markdouble{chapter}{#1} }
\cs_gset:Npn \sectionmark #1
{
@@ -1577,8 +1588,8 @@
\cs_new_protected:Npn \eb_biber_title_level_spec:n #1
{
\bool_if:NTF \l__eb_class_mode_book_bool
- { \bichapter*{#1}{\l__eb_bib_en_bitoc_title_tl} }
- { \bisection*{#1}{\l__eb_bib_en_bitoc_title_tl} }
+ { \bichapter*{#1}{\eb@bib@bitoc@title} }
+ { \bisection*{#1}{\eb@bib@bitoc@title} }
\sectionmark{#1}
}
\cs_new_protected:Npn \eb_toc_start_multi_column_ext:n #1
@@ -1845,7 +1856,7 @@
\SetEnumitemValue{font}{sf}{\color{ctex@emph}\normalfont\sffamily}
\SetEnumitemValue{ref}{enumii}{\arabic{enumi}.\alph*}
\SetEnumitemValue{ref}{enumiii}{\arabic{enumi}.\alph{enumii}.\roman*}
-\setlist{nosep,labelsep = 0.5em,listparindent = 2em}
+\setlist{nosep,labelsep = 0.5em,listparindent = \parindent}
\setlist[1]{leftmargin = *,align = left,mode = unboxed}
\setlist[itemize,1]{label = bullet}
\setlist[itemize,2]{label = endash}
@@ -2119,7 +2130,7 @@
bibstyle .initial:n = numerical,
citestyle .tl_set:N = \l__eb_bib_cite_style_tl,
datafile .clist_set:N = \l__eb_bib_datafile_clist,
- bititle .tl_set:N = \l__eb_bib_en_bitoc_title_tl,
+ bititle .tl_set:N = \eb@bib@bitoc@title,
bititle .initial:n = Bibliography,
unknown .code:n = \eb_msg_abandon_option:n { bibset }
}
@@ -2372,6 +2383,9 @@
\exp_args:NV \hypersetup \l__eb_hyperref_clist
}
+\cs_set_eq:NN \eb@labelformat@save \labelformat
+\cs_set_protected:Npn \labelformat #1#2
+ { \AfterPreamble{\eb@labelformat@save{#1}{#2}} }
\AtBeginDocument
{
\@ifpackageloaded{cleveref}{}
@@ -2419,7 +2433,7 @@
}
%</package>
%<*tcolorbox>
-\ProvidesExplFile{eb-tcolorbox.cfg}{2022/01/15}{1.46C}
+\ProvidesExplFile{eb-tcolorbox.cfg}{2022/01/16}{1.46E}
{Customization of tcolorbox for easybook}
\cs_set_protected:Npn \addtotcbstyle #1#2
diff --git a/macros/latex/contrib/easybook/easybook.pdf b/macros/latex/contrib/easybook/easybook.pdf
index bcb1d7e974..633011029a 100644
--- a/macros/latex/contrib/easybook/easybook.pdf
+++ b/macros/latex/contrib/easybook/easybook.pdf
Binary files differ
diff --git a/macros/latex/contrib/easybook/easybook.tex b/macros/latex/contrib/easybook/easybook.tex
index 39b0334c40..865f7bf26f 100644
--- a/macros/latex/contrib/easybook/easybook.tex
+++ b/macros/latex/contrib/easybook/easybook.tex
@@ -21,8 +21,8 @@
name = easybook,
color-scheme = blue,
title = EASYBOOK 使用手册,
- version = v1.46C,
- date = 2022/01/15,
+ version = v1.46E,
+ date = 2022/01/16,
authors = 瞿毅,
info = 排版简体中文学位论文和书籍,
email = q1jx@foxmail.com,
@@ -415,7 +415,7 @@
style =
{
fntnumwith = page,
- uppercase = false
+ uppercase = first
}
}
\ebstyle{hyphen-figure = {-}}
@@ -440,9 +440,9 @@
\keybool{withpart}\Default{false}
使章标题跟随部分计数器编号,当开启新的一部分时章编号从 1 开始。
\keychoice{fntnumwith}{part,chapter,page}\Default{chapter}
- 使脚注跟随编号的计数器名。默认跟随章计数器,当开启新的一章时脚注编号从 1 开始。
- \keybool{uppercase}\Default{true}
- 使用 \cs*{rightmark} 和 \cs*{leftmark} 等标题标记命令获取标题内容时英文是否大写。
+ 使脚注跟随编号的计数器名。默认跟随章计数器,即开启新的一章时脚注编号从 1 开始。
+ \keychoice{uppercase}{all,first,none}\Default{all}
+ 使用 \cs*{rightmark} 和 \cs*{leftmark} 等标题标记命令获取标题内容用于页眉页脚时其中英文的大小写类型。\code{all} 为标题标记中的英文字母全部大写,\code{first} 为标记以英文起始时仅第一个字母大写,\code{none} 则不改变标记中英文字母的大小写形式。
\kvsplit{brackets}{左括号,右括号}\Default{\Carg{(\black{,})}}
设置行间公式编号标签的括号及格式,以英文逗号分隔,分别代表左右括号。\meta{左括号} 可以是带有一个参数的命令,用于接受编号和 \meta{右括号}。将标签括号设置为方括号,并使用无衬线字体:
\begin{ctexexam}
@@ -708,7 +708,7 @@
\subsection{页眉页脚}
\label{subsec:header and footer}
-模块 \module*{hdrset} 设置的命令由 \pkg*{fancyhdr} 宏包提供支持。在 \cls*{book} 模式时使用章节标题标记选项 \option{chap-mark} 和 \option{sec-mark},在 \cls*{article} 模式时使用 \option{sec-mark} 和 \option{subsec-mark} 选项,这与标准文档类的行为一致。标题标记由标签和标题组成,选项中参数 \code{\#1} 代表当前章、节或小节的标题。也可以直接重新定义这些选项对应的标题标记命令,但此时标记大写选项 \option{uppercase} 失效。
+模块 \module*{hdrset} 设置的命令由 \pkg*{fancyhdr} 宏包提供支持。标题标记由标签和标题组成,选项中参数 \code{\#1} 代表当前章、节或小节的标题。在 \cls*{book} 模式时使用标题标记选项 \option{chap-mark} 和 \option{sec-mark},在 \cls*{article} 模式时使用 \option{sec-mark} 和 \option{subsec-mark} 选项,这与标准文档类的行为一致。重新设置标题标记选项时标记大小写选项 \option{uppercase} 会失效。
\begin{options}
\keyval-{chap-mark}{标题标记}\Module{hdrset}
标题标记命令 \cs*{chaptermark} 的内容,包括了标签选项 \option{chap-label} 的内容。
diff --git a/macros/latex/contrib/kanbun/README.md b/macros/latex/contrib/kanbun/README.md
new file mode 100644
index 0000000000..3b6e755d2d
--- /dev/null
+++ b/macros/latex/contrib/kanbun/README.md
@@ -0,0 +1,24 @@
+# The `kanbun` package
+
+The `kanbun` package, like other *kanbun-kundoku* (漢文訓読) LaTeX packages (such as `gckanbun`), allows users to manually input macros for elements in a *kanbun-kundoku* paragraph.
+
+More importantly, it accepts plain text input in the “*kanbun* annotation” form when used with LuaLaTeX, which allows typesetting *kanbun-kundoku* paragraphs efficiently.
+
+## Licence
+
+Copyright 2022 Yuanhao Chen
+
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in
+ <http://www.latex-project.org/lppl.txt>
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+This work has the LPPL maintenance status `maintained'.
+
+The Current Maintainer of this work is Yuanhao Chen.
+
+This work consists of the files `kanbun.sty`, `kanbun.lua`,
+`kanbun-example.tex` and `kanbun.tex`.
diff --git a/macros/latex/contrib/kanbun/kanbun-example.pdf b/macros/latex/contrib/kanbun/kanbun-example.pdf
new file mode 100644
index 0000000000..f437066ba9
--- /dev/null
+++ b/macros/latex/contrib/kanbun/kanbun-example.pdf
Binary files differ
diff --git a/macros/latex/contrib/kanbun/kanbun-example.tex b/macros/latex/contrib/kanbun/kanbun-example.tex
new file mode 100644
index 0000000000..0ae963112f
--- /dev/null
+++ b/macros/latex/contrib/kanbun/kanbun-example.tex
@@ -0,0 +1,44 @@
+%% Copyright 2022 Yuanhao Chen
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Yuanhao Chen.
+%
+% This work consists of the files kanbun.sty, kanbun.lua,
+% kanbun-example.tex and kanbun.tex.
+%
+% example text from https://phesoca.com/kanbun-html/
+\documentclass{ltjtarticle}
+
+\usepackage[match]{luatexja-fontspec}
+\setmainjfont{Kozuka Mincho Pr6N}
+
+\newlength\myzw
+\setlength\myzw{2.25\zw}
+\usepackage[kumi=beta, unit=\myzw, yokoaki=3.5]{kanbun}
+
+\usepackage[margin=0pt]{geometry}
+
+\usepackage{xcolor}
+
+\Kanbun
+初メテ,帝ノ母劉貴人ハ賜(たま)ハリ[レ]死ヲ,太祖ハ告ゲ[レ]帝ニ曰ハク「昔漢武帝ハ將‹し›«テ»ニ[レ]立タセント[二]其ノ子ヲ[一]而殺シ[二]其ノ母ヲ[一],不[下]令(し)メ[三]婦人ヲ後ロニ與(あづか)ラ[二]國政ニ[一],使(し)メ[中]外家ヲ為(な)サ[上レ]亂ヲ。汝當ニ‹べ›«ク»[二]繼統ス[一],故ニ吾レ遠クシテ同ズルコト[二]漢武ト[一],為(た)リ[二]長久之計[一]。」帝素ヨリ純孝ナリ,哀シク泣キ不[レ]能ハ[二]自ラ勝ツコト[一],太祖怒ル[レ]之レヲ。帝ハ還リ[レ]宮ニ,哀シク不[二]自ラ止マ[一],日夜ニシテ號泣ス。太祖知リテ而又タ召ス[レ]之レヲ。帝欲シ[レ]入ラント,左右曰ハク「孝子事ヘバ[レ]父ニ,小杖則チ受ケ,大杖避ク[レ]之レヲ。今陛下ノ怒ルコト盛ンナリ,入レバ或イハ不測ナリ,陷ラス[二]帝ヲ於不義ニ[一]。不[レ]如カ[二]且(しばら)ク出ヅルニ[一],待チテ[二]怒リノ解クルヲ[一]而進ムコト,不ル[レ]晚カラ也。」帝ハ懼レ,從ヒ[レ]之レニ,乃チ游行シ逃グ[二]於外ニ[一]。
+\EndKanbun
+
+\begin{document}
+\color[HTML]{e0e0e0}
+\pagestyle{empty}
+\vspace*{\fill}
+\begin{minipage}{0.5\pageheight}
+ \printkanbun
+\end{minipage}
+\vspace*{\fill}
+\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/kanbun/kanbun.lua b/macros/latex/contrib/kanbun/kanbun.lua
new file mode 100644
index 0000000000..9f8f01aab3
--- /dev/null
+++ b/macros/latex/contrib/kanbun/kanbun.lua
@@ -0,0 +1,224 @@
+function directtex(str)
+ coroutine.yield(str)
+end
+
+function to_TeX_box(str)
+ directtex("\\ExplSyntaxOn\\newbox\\kanbun_lua_box\\sbox\\kanbun_lua_box{"..str.."}\\ExplSyntaxOff")
+ return tex.getbox('kanbun_lua_box')
+end
+
+function has_value (tab, val)
+ for index, value in ipairs(tab) do
+ if value == val then
+ return true
+ end
+ end
+ return false
+end
+
+function main_loop()
+ brackets = {}
+ --
+ brackets["furigana"] = {"(", ")"}
+ brackets["okurigana"] = {"{","}"} -- allow user to omit
+ brackets["kaeriten"] = {"[","]"}
+ brackets["furigana4saidokumoji"] = {"‹","›"}
+ brackets["okurigana4saidokumoji"] = {"«","»"}
+ --
+ -- other_brackets["punctuation"] = {"⦉","⦊"}
+ -- other_brackets["kanji"] = {"⌊","⌋"}
+ -- other_brackets["multikanji"] = {"‘","’"}
+ -- other_brackets["unit"] = {"“","”"}
+ --
+ left_brackets = {}
+ right_brackets = {}
+ for k,v in pairs(brackets) do
+ table.insert(left_brackets, v[1])
+ table.insert(right_brackets, v[2])
+ end
+
+ -- punctuation_str = "〻―・、,。…「」『』"
+ punctuation_str = "㆐〻―—・、,。…「」『』!?:"
+ left_punctuation_str = "「『"
+
+ lines_chars_table = {}
+ tex_kana_bool = token.create("g_kana_bool")
+ tex_true_bool = token.create("c_true_bool")
+ for i,l in ipairs(verb_table) do
+ split_line = {}
+ for c in l:gmatch(utf8.charpattern) do
+ table.insert(split_line, c)
+ end
+
+ -- some unknown bug (in \matchkana ?) solved by changing the last entry to an empty string if not ascii
+ for i,c in ipairs(split_line) do
+ last_index = i
+ end
+ if utf8.codepoint(split_line[last_index] or " ") < 128 then
+ split_line[last_index+1]=""
+ else
+ split_line[last_index]=""
+ end
+
+ last_bracket_index = 0
+ for j,c in ipairs(split_line) do
+ if has_value(left_brackets, c) then
+ last_bracket_index = j
+ end
+ if last_bracket_index == 0 then
+ directtex("\\matchkana{"..c.."}")
+ if tex_kana_bool.mode == tex_true_bool.mode then
+ split_line[j] = brackets["okurigana"][1]..c..brackets["okurigana"][2]
+ else
+ split_line[j] = "“⌊"..c.."⌋”"
+ end
+ end
+ if has_value(right_brackets, c) then
+ last_bracket_index = 0
+ end
+ end
+ table.insert(lines_chars_table, split_line)
+ end
+
+ annotated_lines_table = {}
+ for i,l in ipairs(lines_chars_table) do
+ line = table.concat(l, "")
+
+ line = string.gsub(line, brackets["okurigana"][2]..brackets["okurigana"][1], "")
+ for k,v in pairs(brackets) do
+ line = string.gsub(line, "”(%"..v[1]..")", "%1")
+ line = string.gsub(line, "(%"..v[2]..")(“)", "%1”%2")
+ end
+ for c in line:gmatch(utf8.charpattern) do
+ last = c
+ end
+ if has_value(right_brackets, last) then
+ str = str .. '”'
+ end
+ line = string.gsub(line, "⌊‘⌋”", "‘")
+ line = string.gsub(line, "“⌊’⌋", "’")
+ for p in punctuation_str:gmatch(utf8.charpattern) do
+ line = string.gsub(line, "”“⌊("..p..")⌋", "⦉%1⦊")
+ end
+ line = string.gsub(line, "⦊⦉", "")
+
+ -- reverse the makeshift bug fix to \matchkana
+ line = string.gsub(line, "“⌊⌋”", "")
+
+ -- process annotated text
+ tmp_number_of_multikanji_braces = {utf8.char(61442), utf8.char(61443)}
+ -- process line into units
+ split_line = {}
+ for c in line:gmatch(utf8.charpattern) do
+ table.insert(split_line, c)
+ end
+ units = {}
+ unit_content = {}
+ last_bracket_index = 0
+ for j,c in ipairs(split_line) do
+ if c == "”" then
+ last_bracket_index = last_bracket_index - 1
+ end
+ if last_bracket_index < 1 then
+ table.insert(units, table.concat(unit_content, ""))
+ unit_content = {}
+ else
+ table.insert(unit_content, c)
+ end
+ if c == "“" then
+ last_bracket_index = last_bracket_index + 1
+ end
+ end
+ -- account for multikanji
+ for j,u in ipairs(units) do
+ split_unit = {}
+ for c in u:gmatch(utf8.charpattern) do
+ table.insert(split_unit, c)
+ end
+ number_of_multikanji = 0
+ local last_k
+ for k,c in ipairs(split_unit) do
+ if c == "“" then
+ number_of_multikanji = number_of_multikanji + 1
+ last_k = k
+ end
+ end
+ for m,c in ipairs(split_unit) do
+ if m == last_k then
+ split_unit[m] = "“"..tmp_number_of_multikanji_braces[1]..number_of_multikanji..tmp_number_of_multikanji_braces[2]
+ end
+ end
+ units[j] = table.concat(split_unit, "")
+ if number_of_multikanji > 0 then
+ units[j] = string.gsub(units[j], "“(.-)”’(.*)", "“%1%2”")
+ units[j] = string.gsub(units[j], "‘", "")
+ tmp_unit = units[j]
+ table.remove(units, j)
+ for new_unit in tmp_unit:gmatch"“(.-)”" do
+ table.insert(units, j, new_unit)
+ j = j + 1
+ end
+ end
+ end
+ for j,u in ipairs(units) do
+ if u == "" then
+ table.remove(units, j)
+ end
+ end
+ next_left_punct_ = ""
+ for j,u in ipairs(units) do
+ right_okuri_ = u:match("%{(.-)%}") or ""
+ kanji_ = u:match("⌊(.-)⌋") or ""
+ right_furi_ = u:match("%((.-)%)") or ""
+ left_furi_ = u:match("‹(.-)›") or ""
+ left_okuri_ = u:match("«(.-)»") or ""
+ punct_ = u:match("⦉(.-)⦊") or ""
+ --
+ -- punct_ = punct_:gsub("―", "\\tateten")
+ -- punct_ = punct_:gsub("—", "\\tateten")
+ -- punct_ = punct_:gsub("〻", "\\ninojiten")
+ --
+ kaeriten_ = u:match("%[(.-)%]") or ""
+ multikanji_ = u:match(tmp_number_of_multikanji_braces[1].."(.-)"..tmp_number_of_multikanji_braces[2]) or 0
+ if punctuation_str:match(kanji_) then
+ punct_ = kanji_
+ kanji_ = ""
+ end
+ left_punct_ = next_left_punct_
+ next_left_punct_ = ""
+ for p_ in punct_:gmatch(utf8.charpattern) do
+ if left_punctuation_str:match(p_) then
+ next_left_punct_ = next_left_punct_ .. p_
+ end
+ end
+ for p_ in left_punctuation_str:gmatch(utf8.charpattern) do
+ punct_ = string.gsub(punct_, p_, "")
+ end
+ if u:match(tmp_number_of_multikanji_braces[1]) then
+ multiruby_raise_by_ = 0
+ for trace_back_index = 1, multikanji_-1 do
+ multiruby_raise_by_ = multiruby_raise_by_ + to_TeX_box(units[j - trace_back_index]).width/(kanbunzwtosp)
+ end
+ units[j - multikanji_ + 1] = units[j - multikanji_ + 1]:gsub("\\kanjiunit", "\\hbox{\\kanjiunit")
+ units[j] = "\\kanjiunit{\\multifuriokuri["..multiruby_raise_by_.."]{"..right_furi_.."}{"..right_okuri_.."}}{"..left_punct_.."}{"..kanji_.."}{"..punct_.."}{"..kaeriten_.."}{\\multifuriokuri["..multiruby_raise_by_.."]{"..left_furi_.."}{"..left_okuri_.."}}}"
+ else
+ if kanji_ == "" then
+ units[j] = ""
+ else
+ units[j] = "\\kanjiunit{\\furiokuri{"..right_furi_.."}{"..right_okuri_.."}}{"..left_punct_.."}{"..kanji_.."}{"..punct_.."}{"..kaeriten_.."}{\\furiokuri{"..left_furi_.."}{"..left_okuri_.."}}"
+ end
+ end
+ end
+ line = table.concat(units, "")
+
+ table.insert(annotated_lines_table, line)
+ end
+
+ -- ouput
+ output = "{\\kanbunfont"..table.concat(annotated_lines_table, "\\par").."\\par}"
+ directtex("\\def\\printkanbun{"..output.."}")
+ directtex("\\def\\printkanbuncode{\\directlua{print('')print(output)}}")
+
+ -- end loop in TeX
+ directtex("\\continuefalse")
+end
diff --git a/macros/latex/contrib/kanbun/kanbun.pdf b/macros/latex/contrib/kanbun/kanbun.pdf
new file mode 100644
index 0000000000..a3b0cbdd30
--- /dev/null
+++ b/macros/latex/contrib/kanbun/kanbun.pdf
Binary files differ
diff --git a/macros/latex/contrib/kanbun/kanbun.sty b/macros/latex/contrib/kanbun/kanbun.sty
new file mode 100644
index 0000000000..70994ab463
--- /dev/null
+++ b/macros/latex/contrib/kanbun/kanbun.sty
@@ -0,0 +1,317 @@
+%% Copyright 2022 Yuanhao Chen
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Yuanhao Chen.
+%
+% This work consists of the files kanbun.sty, kanbun.lua,
+% kanbun-example.tex and kanbun.tex.
+%
+\NeedsTeXFormat{LaTeX2e}[2021/06/01]
+\RequirePackage{expl3,xparse,l3keys2e,ifluatex}
+\ProvidesExplClass{kanbun}
+ {2022/01/15} {1.0} {漢文の訓点文の組版}
+
+\ExplSyntaxOn
+\cs_generate_variant:Nn \str_if_eq:nnTF { V }
+\cs_generate_variant:Nn \str_case:nnTF { V }
+
+% vars used in options
+\tl_set:Nn \kanbun_scale { 2 }
+\newlength\kanbun_init_zw
+\setlength\kanbun_init_zw{1em}
+\@ifpackageloaded{luatexja-fontspec}{
+ \tl_set:Nn \kanbun_rubyfontcmd_default { \addjfontfeatures{RawFeature={+ruby}} }
+ \tl_set:Nn \kanbun_fontcmd_default { \addjfontfeatures{RawFeature={+trad}} }
+}{
+ \tl_set:Nn \kanbun_rubyfontcmd_default {}
+ \tl_set:Nn \kanbun_fontcmd_default {}
+}
+
+% options
+\keys_define:nn { kanbun }
+ {
+ , scale .tl_set:N = \kanbun_scale
+ , scale .initial:n = { 2 }
+ , fontcmd .tl_set:N = \kanbun_fontcmd
+ , fontcmd .initial:n = \kanbun_fontcmd_default
+ , rubyfontcmd .tl_set:N = \kanbun_rubyfontcmd
+ , rubyfontcmd .initial:n = \kanbun_rubyfontcmd_default
+ , unit .tl_set:N = \kanbun_zw
+ , unit .initial:n = { \kanbun_init_zw }
+ , yokoaki .tl_set:N = \kanbun_yokoaki
+ , yokoaki .initial:n = { \kanbun_scale }
+ , tateaki .tl_set:N = \kanbun_tateaki
+ , tateaki .initial:n = { 2 }
+ , okuriprotrusion .tl_set:N = \kanbun_okuriprotrusion
+ , okuriprotrusion .initial:n = { 1 }
+ , kumi .tl_set:N = \kanbun_kumi
+ , kumi .initial:n = { aki }
+ , aki .code:n = \keys_set:nn { kanbun } { kumi = aki }
+ , beta .code:n = \keys_set:nn { kanbun } { kumi = beta }
+ }
+\ProcessKeysOptions { kanbun }
+
+% other vars
+\tl_set:Nn \kanbun_rubyfontsize_rubyfontcmd { \kanbun_rubyfontcmd\fontsize{\fp_eval:n {1/\kanbun_scale}\kanbun_zw}{0pt}\selectfont }
+\newlength{\kanbun_furilen}
+\tl_set:Nn \kanbun_tateten_width { 1/30 }
+\tl_set:Nn \kanbunzwtosp { \fp_eval:n {\dim_ratio:nn { 1 \kanbun_zw } { 1 sp } } }
+\tl_set:Nn \kanbun_unit_glue {
+ \str_if_eq:VnTF \kanbun_kumi { aki } {
+ \penalty0
+ }
+ {
+ \hskip 0\kanbun_zw plus 0.25\kanbun_zw minus 0\kanbun_zw
+ }
+}
+\tl_set:Nn \kanbun_punct_glue {
+ \hskip 0\kanbun_zw plus 0.5\kanbun_zw minus 0\kanbun_zw
+}
+
+% \kanjiunit and other macros to be used in a \kanjiunit
+\NewDocumentCommand { \kanbun_ensure_height } { m m }
+ {
+ \vbox to #1{\vss{#2}\vss}
+ }
+\newbox\kanbun_current_kanjiunit
+\NewDocumentCommand { \kanjiunit } { m m m m m m }
+ {
+ \tl_set:Nn \ninojiten_punct {}
+ \tl_set:Nn \right_punct {}
+ \tl_set:Nn \central_punct {}
+ \process_punct{ #4 }
+ \tl_set:Nn \kanbun_central_punct_box {
+ \kanbun_ensure_height{1\kanbun_zw} {
+ \str_if_eq:VnTF \kanbun_kumi { aki }
+ {
+ \hbox{\kern 1\kanbun_zw{\hbox to \fp_eval:n { \kanbun_tateaki/\kanbun_scale }\kanbun_zw{\hss{\central_punct}\hss}}}
+ }
+ {
+ \hbox{\kern 1\kanbun_zw{\central_punct}}
+ }
+ }
+ }
+ \tl_set:Nn \kanbun_left_punct_phantom {
+ \kanbun_ensure_height{1\kanbun_zw} {
+ \str_if_eq:VnTF \kanbun_kumi { aki } { }
+ {
+ \str_if_eq:nnTF { #2 } { } { } {
+ \hbox{\phantom{\hbox to 0.5\kanbun_zw{\hss#2\hfil}}}
+ }
+ }
+ }
+ }
+ \tl_set:Nn \kanbun_right_punct_box {
+ \kanbun_ensure_height{1\kanbun_zw} {
+ \str_if_eq:VnTF \right_punct { } { } {
+ \hbox{\kern 1\kanbun_zw{\right_punct}}
+ }
+ }
+ }
+ %
+ \tl_set:Nn \unit_content {
+ \kanbun_left_punct_phantom % compensate for width of left punct
+ \vbox{
+ \kanbun_ensure_height{\fp_eval:n { 1/\kanbun_scale }\kanbun_zw}{\hbox{\kanbun_rubyfontsize_rubyfontcmd{#1}}} % right kana
+ \nointerlineskip %
+ \kanbun_ensure_height{1\kanbun_zw}{\llap{#2}} % left punct
+ \nointerlineskip %
+ \vspace*{-1 \kanbun_zw}
+ \kanbun_ensure_height{1\kanbun_zw}{
+ \hbox to 1\kanbun_zw{\hss{#3}\hss}
+ } % kanji
+ \nointerlineskip %
+ \vspace*{-1 \kanbun_zw}
+ \kanbun_ensure_height{\fp_eval:n { 1/\kanbun_scale }\kanbun_zw}{\hbox{\kern 1\kanbun_zw{\ninojiten_punct}}} % ninojiten
+ \nointerlineskip %
+ \vspace*{\fp_eval:n { -1/\kanbun_scale }\kanbun_zw}
+ \kanbun_right_punct_box % right punct
+ \nointerlineskip %
+ \vspace*{-1\kanbun_zw}
+ \kanbun_central_punct_box % central punct
+ \nointerlineskip %
+ \vspace*{ \fp_eval:n { -1/\kanbun_scale }\kanbun_zw }
+ \kanbun_ensure_height{\fp_eval:n { 1/\kanbun_scale }\kanbun_zw}{\hbox{\kanbun_rubyfontsize_rubyfontcmd\kern 1\kanbun_zw{\kaeriten{#5}}}} % kaeriten
+ \nointerlineskip %
+ \kanbun_ensure_height{\fp_eval:n { 1/\kanbun_scale }\kanbun_zw}{\hbox{\kanbun_rubyfontsize_rubyfontcmd{#6}}} % left kana
+ }
+ }
+ \str_if_eq:VnTF \kanbun_kumi { aki } {
+ \setbox\kanbun_current_kanjiunit \hbox to \fp_eval:n { 1+\kanbun_tateaki/\kanbun_scale }\kanbun_zw{ \unit_content }
+ }{
+ \setbox\kanbun_current_kanjiunit \hbox{ \unit_content }
+ }
+ %
+ % output
+ \str_if_eq:VnTF \kanbun_kumi { aki } { }
+ {
+ \str_if_eq:nnTF { #2 } { } { } {
+ \kanbun_punct_glue
+ }
+ }
+ \nobreak
+ \str_if_eq:VnTF \kanbun_kumi { aki }
+ {
+ \usebox\kanbun_current_kanjiunit
+ }
+ {
+ \discretionary{
+ \usebox\kanbun_current_kanjiunit\kern\dimexpr1\kanbun_zw-\wd\kanbun_current_kanjiunit\relax
+ }{
+ %
+ }{
+ \usebox\kanbun_current_kanjiunit
+ }
+ }
+ \nobreak
+ \str_if_eq:VnTF \kanbun_kumi { aki } { }
+ {
+ \str_if_eq:VnTF \right_punct { } { } {
+ \kanbun_punct_glue
+ }
+ }
+ \nobreak
+ \kanbun_unit_glue
+ }
+\NewDocumentCommand { \furiokuri } { m m }
+ {
+ \settowidth{\kanbun_furilen}{#1}
+ \ifdim\kanbun_furilen < \fp_eval:n {1-\kanbun_okuriprotrusion/\kanbun_scale}\kanbun_zw
+ \makebox[\fp_eval:n {1-\kanbun_okuriprotrusion/\kanbun_scale}\kanbun_zw][l]{#1}
+ \else
+ #1
+ \fi
+ #2
+ }
+\NewDocumentCommand { \kaeriten } { m }
+ {
+ \tl_set:Nn \kaeriten_output { #1 }
+ \sys_if_engine_xetex:TF {} {
+ \platex_if_direction_tate:TF {
+ \str_case:VnTF \kaeriten_output {
+ { 一レ } { \tl_set:Nn \kaeriten_output { \kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw 一\kern \fp_eval:n {-0.75/\kanbun_scale}\kanbun_zw レ } }
+ { 甲レ } { \tl_set:Nn \kaeriten_output { 甲\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw レ } }
+ { 上レ } { \tl_set:Nn \kaeriten_output { 上\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw レ } }
+ { 天レ } { \tl_set:Nn \kaeriten_output { 天\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw レ } }
+ } {} {}
+ } {}
+ }
+ \tl_use:N \kaeriten_output
+ }
+\NewDocumentCommand { \process_punct_map } { m } {
+ \str_case:nnTF { #1 } {
+ { — } { \tl_put_right:Nn \central_punct { \tateten } }
+ { ― } { \tl_put_right:Nn \central_punct { \tateten } }
+ { ㆐ } { \tl_put_right:Nn \central_punct { \tateten } }
+ % { : } { \tl_put_right:Nn \central_punct { \hbox to 1\kanbun_zw{\hss{:}\hss} } }
+ % { ・ } { \tl_put_right:Nn \central_punct { \hbox to 1\kanbun_zw{\hss{・}\hss} } }
+ { : } { \tl_put_right:Nn \right_punct { \hbox to 0.5\kanbun_zw{\hss{:}\hss} } }
+ { ・ } { \tl_put_right:Nn \right_punct { \hbox to 0.5\kanbun_zw{\hss{・}\hss} } }
+ { … } { \tl_put_right:Nn \central_punct { \hbox to 1\kanbun_zw{\hss{…}\hss} } }
+ { ! } { \tl_put_right:Nn \central_punct { \hbox to 1\kanbun_zw{\hss{!}\hss} } }
+ { ? } { \tl_put_right:Nn \central_punct { \hbox to 1\kanbun_zw{\hss{?}\hss} } }
+ { 〻 } {
+ \tl_put_right:Nn \ninojiten_punct { \ninojiten }
+ \tl_put_right:Nn \right_punct { \phantom{\ninojiten} }
+ }
+ } {} {
+ \tl_put_right:Nn \right_punct { \hbox to 0.5\kanbun_zw{\hfil#1\hss} }
+ }
+}
+\NewDocumentCommand { \process_punct } { m }
+ {
+ \str_map_function:nN { #1 } \process_punct_map
+ }
+\NewDocumentCommand { \multifuriokuri } { O{2\kanbun_zw} m m }
+ {
+ \kanbun_rubyfontcmd
+ \kern \fp_eval:n { -(#1) }\kanbun_zw
+ \makebox[\fp_eval:n { (#1) + 1 - \kanbun_okuriprotrusion/\kanbun_scale }\kanbun_zw][s]{#2}
+ #3
+ }
+
+% these commands are used as punct
+\NewDocumentCommand { \tateten } {}
+ {
+ \str_if_eq:VnTF \kanbun_kumi { aki } {
+ \makebox[\fp_eval:n {\kanbun_tateaki/\kanbun_scale}\kanbun_zw][c]{
+ \rule[\fp_eval:n {-\kanbun_tateten_width/2}\kanbun_zw]{\fp_eval:n {\kanbun_tateaki/\kanbun_scale}\kanbun_zw}{\fp_eval:n {\kanbun_tateten_width}\kanbun_zw}
+ }
+ }{
+ \makebox[\fp_eval:n {1/\kanbun_scale}\kanbun_zw][c]{
+ \rule[\fp_eval:n {-\kanbun_tateten_width/2}\kanbun_zw]{\fp_eval:n {1/\kanbun_scale}\kanbun_zw}{\fp_eval:n {\kanbun_tateten_width}\kanbun_zw}
+ }
+ }
+ }
+\NewDocumentCommand { \ninojiten } {}
+ { \kanbun_rubyfontsize_rubyfontcmd 〻 }
+
+% corrects fontsize of ruby base
+\NewDocumentCommand { \kanbunfont } {} { \parindent=0pt\kanbun_fontcmd\fontsize{\kanbun_zw}{\fp_eval:n {1+\kanbun_yokoaki/\kanbun_scale}\kanbun_zw}\selectfont}
+\NewDocumentEnvironment { kanjipar } { +b }
+ {
+ {
+ \kanbunfont
+ #1
+ \par
+ }
+ } {}
+
+% for LuaLaTeX to parse Kanbun annotation
+\NewDocumentCommand{\matchkana}{ m }{
+ \regex_set:Nn \c_kana_regex {[\x{3040}-\x{30FA}\x{30FC}-\x{30FF}\x{31F0}-\x{31FF}\x{FF66}-\x{FF9F}\x{1B100}-\x{1B122}\x{1AFF0}-\x{1AFFF}\x{1B000}-\x{1B0FF}\x{1B130}-\x{1B16F}]}
+ \regex_match:NnTF \c_kana_regex { #1 } { \bool_set_true:N \g_kana_bool } { \bool_set_false:N \g_kana_bool }
+}
+%
+\ExplSyntaxOff
+%
+\ifluatex
+% verbatim reader adapted from https://tex.stackexchange.com/a/361759
+\directlua{
+verb_table = {}
+function store_lines (str)
+ if string.find (str , "\noexpand\\EndKanbun" ) then
+ luatexbase.remove_from_callback (
+ "process_input_buffer" , "store_lines")
+ return "\\newif\\ifcontinue\\continuetrue\\directlua { co = coroutine.create(main_loop) }\\loop\\directlua{ ok,b=coroutine.resume(co) tex.sprint(b) }\\ifcontinue\\repeat"
+ else
+ table.insert(verb_table, str)
+ end
+ return ""
+end
+function register_verbatim ()
+ verb_table = {}
+ luatexbase.add_to_callback(
+ "process_input_buffer" , store_lines , "store_lines")
+end
+% require main loop
+kanbunzwtosp = \luaescapestring{\kanbunzwtosp}
+require("kanbun.lua")
+}
+\def\Kanbun{\directlua{register_verbatim()}}
+\def\createcatcodes{%
+ \bgroup%
+ \catcode`\\=12 \catcode`\{=12 \catcode`\}=12%
+ \catcode`\$=12 \catcode`\&=12 \catcode`\^^M=13%
+ \catcode`\#=12 \catcode`\^=12 \catcode`\_=12%
+ \catcode`\ =13 \catcode`\~=12 \catcode`\%=12%
+ \savecatcodetable 1%
+ \egroup%
+}
+\createcatcodes
+\bgroup%
+ \catcode`\^^M=13\gdef^^M{\quitvmode\par}%
+ \catcode`\ = 13\gdef {\quitvmode\Space}%
+\egroup%
+\def\Space{ }
+%
+\fi
diff --git a/macros/latex/contrib/kanbun/kanbun.tex b/macros/latex/contrib/kanbun/kanbun.tex
new file mode 100644
index 0000000000..02e4c0e918
--- /dev/null
+++ b/macros/latex/contrib/kanbun/kanbun.tex
@@ -0,0 +1,301 @@
+%% Copyright 2022 Yuanhao Chen
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Yuanhao Chen.
+%
+% This work consists of the files kanbun.sty, kanbun.lua,
+% kanbun-example.tex and kanbun.tex.
+%
+\documentclass[12pt]{ltxdockit}
+
+\AfterTOCHead[toc]{\sffamily}
+\makeatletter
+ \def\@seccntformat#1{\protect\makebox[0pt][r]{\csname the#1\endcsname\hspace{\marglistsep}}}
+\makeatother
+
+\usepackage{shortvrb}
+\MakeShortVerb{|}
+
+\lstnewenvironment{example}[1][]
+ {\lstset{
+ basicstyle=\ttfamily,
+ frame=single,
+ columns=flexible,
+ language=[LaTeX]TeX,
+ breaklines=true,
+ postbreak=\mbox{\textcolor{spot}{$\hookrightarrow$}\space},
+ % morekeywords={drawuntpoint,untpoint,linkuntpoints},
+ % escapeinside={<@}{@>},
+ }}
+ {}
+
+\usepackage{luatexja}
+ \ltjdefcharrange{10}{"2E3A}
+ \ltjdefcharrange{11}{"2039-"203A}
+ \ltjsetparameter{jacharrange={-1, +2, +3, -4, -5, +6, +7, -8, +9, +10, -11}}
+\usepackage[match]{luatexja-fontspec}
+\defaultfontfeatures{Numbers=OldStyle, Scale=MatchLowercase}
+\defaultjfontfeatures{Scale=MatchLowercase}
+\setmainjfont{Kozuka Mincho Pr6N}
+\setsansjfont{Sarasa Mono J}
+\setmonojfont[YokoFeatures={JFM=prop}]{Sarasa Mono J}
+\setmainfont{Minion Pro}
+\setsansfont{Myriad Pro}
+\setmonofont{Sarasa Mono J}
+\newfontfamily{\kanbunfamily}{Kozuka Mincho Pr6N}
+
+\usepackage{luatexja-ruby}
+ \ltjsetruby{fontcmd=\addjfontfeature{RawFeature={+ruby}}}
+
+\usepackage{kanbun}
+\newcommand{\printkanbunblock}[2]{
+ {
+ \parindent=0pt
+ \vspace*{1\zw}
+ \hfill
+ \vbox{
+ \hsize=#1\zw
+ {
+ \tate
+ \addjfontfeature{Scale=1}
+ #2
+ }
+ }
+ \hfill
+ \vspace*{1\zw}
+ }
+}
+
+\usepackage{bxtexlogo}
+\usepackage{realscripts}
+\usepackage{microtype}
+
+\usepackage{wallpaper}
+
+\Kanbun
+以テ[二]羅(ら)蝶(てふ)ヲ[一]作ルガ[二]漢文訓読ヲ[一]用(ため)ノ包(ぱつけーぢ)
+\EndKanbun
+\title{The \sty{kanbun} package}
+\subtitle{\normalsize\normalfont\addjfontfeature{Scale=1}\printkanbun}
+\author{Yuanhao Chen (\ruby[rubysmash=true]{陳|元|鎬}{ちん|げん|こう})}
+\date{\scshape 15 january 2022, v1.0}
+
+
+\begin{document}
+
+\ThisCenterWallPaper{1}{kanbun-example.pdf}
+\ExplSyntaxOn
+\tl_set:Nn \kanbun_kumi { beta }
+\ExplSyntaxOff
+\maketitle
+\tableofcontents
+
+
+\section{Introduction}
+The \sty{kanbun} package, like other \emph{kanbun-kundoku} (漢文訓読) \LaTeX{} packages (such as \sty{gckanbun}), allows users to manually input macros for elements in a \emph{kanbun-kundoku} paragraph.
+
+More importantly, it accepts plain text input in the ``\emph{kanbun} annotation'' form when used with \LuaLaTeX, which allows typesetting \emph{kanbun-kundoku} paragraphs efficiently\footnote{The idea comes from \href{https://phesoca.com/kanbun-html/}{漢文\textsc{html}} by UntPhesoca, which is a JavaScript and \textsc{css} implementation.}.
+
+
+\section{Basic example with \LuaLaTeX}
+As seen in the following example, typesetting a \emph{kanbun-kundoku} paragraph with the \sty{kanbun} package requires only light annotations --- it automatically transforms the annotated plain text into \LaTeX{} macros through Lua, rather than having users type in macros themselves.
+
+\ExplSyntaxOn
+\tl_set:Nn \kanbun_tateaki { 1 }
+\tl_set:Nn \kanbun_kumi { aki }
+\ExplSyntaxOff
+\Kanbun
+月落チ烏啼キテ霜満ツ[レ]天ニ,
+江楓漁火対ス[二]愁眠ニ[一]。
+姑(こ)蘇(そ)城外ノ寒山寺,
+夜半ノ鐘声到ル[二]客船ニ[一]。
+\EndKanbun
+
+\penalty0
+\printkanbunblock{13}{\printkanbun}
+\vspace{-2\zw}
+
+\begin{example}
+\documentclass{ltjtarticle}
+\usepackage[kumi=aki, tateaki=1]{kanbun}
+\begin{document}
+\Kanbun
+月落チ烏啼キテ霜満ツ[レ]天ニ,
+江楓漁火対ス[二]愁眠ニ[一]。
+姑(こ)蘇(そ)城外ノ寒山寺,
+夜半ノ鐘声到ル[二]客船ニ[一]。
+\EndKanbun
+\printkanbun
+\end{document}
+\end{example}
+
+Note that if you want to use this functionality, you have to run this document with \LuaLaTeX.
+
+
+\section{Usage}
+
+\subsection{Package options}
+Load the package with
+\begin{ltxsyntax}
+ \cmditem{usepackage}\oprm{\sty{kanbun} options}|{kanbun}|
+\end{ltxsyntax}
+
+This package provides a variety of customisable features in \emph{kanbun-kundoku}.
+
+\begin{optionlist}
+ \optitem[]{scale}{\prm{ratio}}
+ Sets the ratio of the size of \emph{kanji} to that of ruby texts. Default: \verb|2|.
+
+ \optitem[]{fontcmd}{\prm{font command}}
+ Sets the font command to use for \emph{kanji}. If \sty{luatexja-fontspec} is loaded, it is set default to \verb|\addjfontfeatures{RawFeature={+trad}}| to obtain traditional \emph{kanji} if applicable.
+
+ \optitem[]{rubyfontcmd}{\prm{font command}}
+ Sets the font command to use for ruby texts. If \sty{luatexja-fontspec} is loaded, it is set default to \verb|\addjfontfeatures{RawFeature={+ruby}}| to obtain ruby glyphs when applicable.
+
+ \optitem[]{unit}{\prm{length}}
+ Sets the base size (size of \emph{kanji}). Default: \verb|\kanbun_zw|, which is initialised as \verb|1em|.
+
+ \optitem[]{yokoaki}{\prm{ratio}}
+ Sets the horizontal space between \emph{kanji} with respect to the size of ruby texts. Default: \verb|2|.
+
+ \optitem[]{tateaki}{\prm{ratio}}
+ Sets the vertical space between \emph{kanji} with respect to the size of ruby texts. Default: \verb|2|.
+
+ \optitem[]{okuriprotrusion}{\prm{ratio}}
+ Sets how much \emph{okurigana} should be vertically tucked into the space of \emph{kanji} with respect to the size of ruby texts, if that does not cause an overlap with \emph{furigana}. Default: \verb|1|.
+
+ \optitem[]{kumi}{\opt{aki}, \opt{beta}}
+ Sets whether to use \emph{aki-gumi} (typeset with uniform inter-character spacing) or \emph{beta-gumi} (typeset with no inter-character space between adjacent character frames). Or simply call \opt{aki} or \opt{beta} without \opt{kumi=}. Default: \opt{aki}.
+\end{optionlist}
+
+After initialising the options, you can still change the option values through \sty{exlp3} syntax, with a prefix \verb|\kanbun_| to option names. For example, to switch to \emph{beta-gumi}, you could use
+\begin{example}
+\ExplSyntaxOn
+\tl_set:Nn \kanbun_kumi { beta }
+\ExplSyntaxOff
+\end{example}
+
+\subsection[Basic usage without \LuaLaTeX]{Basic usage without \LuaLaTeX{} (not recommended)}
+When not using the advanced \emph{kanbun}-annotation functionality, it is possible to typeset \emph{kanbun} with any engine with \textsc{cjk} support, such as using \XeLaTeX{} with the \sty{xeCJK} package, or using \upLaTeX{} with \sty{utarticle} or other appropriate class.
+
+\begin{ltxsyntax}
+ \cmditem{kanjiunit}\verb|{ |\cmd{furiokuri}\mprm{right furigana}\mprm{right okurigana}\verb| }|\vspace{-5pt}\\
+ \mprm{left punctuation (e.g.~`「')}\\
+ \mprm{kanji}\\
+ \mprm{other punctuation}\\
+ \mprm{kaeriten}\\
+ \verb|{ |\cmd{furiokuri}\mprm{left furigana}\mprm{left okurigana}\verb| }|
+
+ \cmditem{kanbunfont}
+
+ Sets the font size of \emph{kanji}. Use when the \opt{unit} option is set different to the document's default font size.
+
+ Use \cmd{multifuriokuri} instead of \cmd{furiokuri} if you are putting \emph{furigana} to multiple kanji.
+
+ \cmditem{multifuriokuri}\oprm{length by which {furigana} is raised}\mprm{furigana}\mprm{okurigana}
+\end{ltxsyntax}
+
+For example, the code
+\begin{example}
+% example text from https://phesoca.com/kanbun-html/
+\kanbunfont
+\kanjiunit{}{}{子}{}{}{}
+\kanjiunit{\furiokuri{}{ク}}{}{曰}{,}{}{}
+\kanjiunit{\furiokuri{}{ゾ}}{}{盍}{}{三}{\furiokuri{}{ル}}
+\kanjiunit{}{}{各}{〻}{}{}
+\kanjiunit{\furiokuri{}{ハ}}{}{言}{}{二}{}
+\kanjiunit{\furiokuri{}{ノ}}{}{爾}{}{}{}
+\kanjiunit{\furiokuri{}{ヲ}}{}{志}{。}{一}{}
+\par
+\end{example}
+outputs
+
+\printkanbunblock{6}{
+\kanbunfont
+\kanjiunit{}{}{子}{}{}{}
+\kanjiunit{\furiokuri{}{ク}}{}{曰}{,}{}{}
+\kanjiunit{\furiokuri{}{ゾ}}{}{盍}{}{三}{\furiokuri{}{ル}}
+\kanjiunit{}{}{各}{〻}{}{}
+\kanjiunit{\furiokuri{}{ハ}}{}{言}{}{二}{}
+\kanjiunit{\furiokuri{}{ノ}}{}{爾}{}{}{}
+\kanjiunit{\furiokuri{}{ヲ}}{}{志}{。}{一}{}
+\par
+}
+
+\noindent
+with \opt{tateaki} set to \verb|1|.
+
+\subsection{Usage with \LuaLaTeX}
+\emph{Kanbun} annotation uses the following brackets to mark different elements in \emph{kanbun-kundoku} (as described in \href{https://phesoca.com/kanbun-html/}{漢文\textsc{html}} by UntPhesoca).
+\begin{itemize}
+ \item \verb|( )|: \emph{furigana} (振り仮名)
+ \item \verb|{ }|: \emph{okurigana} (送り仮名) (these brackets can be omitted)
+ \item \verb|‹ ›|: \emph{furigana} (振り仮名) of \emph{saidoku-moji} (再読文字)
+ \item \verb|« »|: \emph{okurigana} (送り仮名) of \emph{saidoku-moji} (再読文字)
+ \item \verb|[ ]|: \emph{kaeriten} (返り点)
+ \item \verb|‘ ’|: multiple \emph{kanji}, potentially with \emph{tateten} inserted, as a ruby base; group ruby (グループルビ)
+ \item no annotation: \emph{kanji} (漢字) and punctuation.
+\end{itemize}
+\emph{Tateten} (竪点) can be input with either \verb|―| (\verb|U+2015|), \verb|—| (\verb|U+2014|) or \verb|㆐| (\verb|U+3190|).
+
+\begin{ltxsyntax}
+ \cmditem{Kanbun}\cmditem{EndKanbun}
+
+ Write the annotated \emph{kanbun} between the commands \cmd{Kanbun} and \cmd{EndKanbun}, and it will be processed and saved, ready to be used later.
+
+ \cmditem{printkanbun}
+
+ Where you would like to use the most recently saved \emph{kanbun-kundoku} paragraph, use \cmd{printkanbun}.
+
+ \cmditem{printkanbuncode}
+
+ If you wish to make modifications on the result or to use the result with a non-\LuaTeX{} engine, it is possible to obtain the macros using \cmd{printkanbuncode} (prints in the terminal), and continue to work from there.
+\end{ltxsyntax}
+
+You can always save \cmd{printkanbun} to a macro and start a new annotated \emph{kanbun} block, as in the following example.
+\begin{example}
+% example text from https://phesoca.com/kanbun-html/
+\documentclass{ltjtarticle}
+\usepackage[kumi=beta]{kanbun}
+
+\Kanbun
+此レ乃チ信(しん)之‘所―[三]以’(ゆゑん)為ル[二]陛下ノ禽(とりこ)ト[一]也。
+\EndKanbun
+\let\信\printkanbun
+
+\Kanbun
+孤之有ルハ[二]孔明[一],猶ホ‹ごと›«キ»[二]魚之有ルガ[一レ]水也。
+\EndKanbun
+\let\孔明\printkanbun
+
+\begin{document}
+\孔明\par\bfseries\信
+\end{document}
+\end{example}
+
+\Kanbun
+此レ乃チ信(しん)之‘所―[三]以’(ゆゑん)為ル[二]陛下ノ禽(とりこ)ト[一]也。
+\EndKanbun
+\let\信\printkanbun
+
+\Kanbun
+孤之有ルハ[二]孔明[一],猶ホ‹ごと›«キ»[二]魚之有ルガ[一レ]水也。
+\EndKanbun
+\let\孔明\printkanbun
+
+\ExplSyntaxOn
+\tl_set:Nn \kanbun_kumi { beta }
+\ExplSyntaxOff
+\printkanbunblock{16}{\孔明\par\bfseries\信}
+
+
+\end{document}
diff --git a/macros/latex/contrib/llncs/README.md b/macros/latex/contrib/llncs/README.md
new file mode 100644
index 0000000000..de41045d18
--- /dev/null
+++ b/macros/latex/contrib/llncs/README.md
@@ -0,0 +1,40 @@
+# llncs
+
+_2022/01/12 v2.21_
+
+Copyright (c) 1996-2022 Springer
+
+Email: [lncs@springer.com](mailto:lncs@springer.com)
+
+Springer's llncs document class and bibliography style for contributions to
+Lecture Notes in Computer Science (LNCS) and other proceedings book series.
+
+---
+
+## Contents
+
+It consists of the following files:
+
+* readme.txt&nbsp;&nbsp;(this file)
+
+* history.txt&nbsp;&nbsp;(the version history of the package)
+
+* llncs.cls&nbsp;&nbsp;(the LaTeX2e document class)
+
+* llncsdoc.tex&nbsp;&nbsp;(the documentation of the class, LaTeX souce)
+
+* llncsdoc.pdf&nbsp;&nbsp;(the documentation of the class, PDF file)
+
+* splncs04.bst&nbsp;&nbsp;(LNCS BibTeX style with alphabetic sorting)
+
+
+## Installation
+
+Copy `llncs.cls` and `splncs04.bst` in a directory that is searched by LaTeX,
+e.g. either your `texmf` tree or the local directory with your main LaTeX
+file.
+
+## License
+
+This work may be distributed and/or modified under the conditions of the CC
+BY license, version 4.0 or later.
diff --git a/macros/latex/contrib/llncs/history.txt b/macros/latex/contrib/llncs/history.txt
new file mode 100644
index 0000000000..79a199ccd4
--- /dev/null
+++ b/macros/latex/contrib/llncs/history.txt
@@ -0,0 +1,144 @@
+Version history for the LLNCS LaTeX2e class
+
+ date filename version action/reason/acknowledgements
+----------------------------------------------------------------------------
+ 29.5.96 letter.txt beta naming problems (subject index file)
+ thanks to Dr. Martin Held, Salzburg, AT
+
+ subjindx.ind renamed to subjidx.ind as required
+ by llncs.dem
+
+ history.txt introducing this file
+
+ 30.5.96 llncs.cls incompatibility with new article.cls of
+ 1995/12/20 v1.3q Standard LaTeX document class,
+ \if@openbib is no longer defined,
+ reported by Ralf Heckmann and Graham Gough
+ solution by David Carlisle
+
+ 10.6.96 llncs.cls problems with fragile commands in \author field
+ reported by Michael Gschwind, TU Wien
+
+ 25.7.96 llncs.cls revision a corrects:
+ wrong size of text area, floats not \small,
+ some LaTeX generated texts
+ reported by Michael Sperber, Uni Tuebingen
+
+ 16.4.97 all files 2.1 leaving beta state,
+ raising version counter to 2.1
+
+ 8.6.97 llncs.cls 2.1a revision a corrects:
+ unbreakable citation lists, reported by
+ Sergio Antoy of Portland State University
+
+11.12.97 llncs.cls 2.2 "general" headings centered; two new elements
+ for the article header: \email and \homedir;
+ complete revision of special environments:
+ \newtheorem replaced with \spnewtheorem,
+ introduced the theopargself environment;
+ two column parts made with multicol package;
+ add ons to work with the hyperref package
+
+07.01.98 llncs.cls 2.2 changed \email to simply switch to \tt
+
+25.03.98 llncs.cls 2.3 new class option "oribibl" to suppress
+ changes to the thebibliograpy environment
+ and retain pure LaTeX codes - useful
+ for most BibTeX applications
+
+16.04.98 llncs.cls 2.3 if option "oribibl" is given, extend the
+ thebibliograpy hook with "\small", suggested
+ by Clemens Ballarin, University of Cambridge
+
+20.11.98 llncs.cls 2.4 pagestyle "titlepage" - useful for
+ compilation of whole LNCS volumes
+
+12.01.99 llncs.cls 2.5 counters of orthogonal numbered special
+ environments are reset each new contribution
+
+27.04.99 llncs.cls 2.6 new command \thisbottomragged for the
+ actual page; indention of the footnote
+ made variable with \fnindent (default 1em);
+ new command \url that copys its argument
+
+ 2.03.00 llncs.cls 2.7 \figurename and \tablename made compatible
+ to babel, suggested by Jo Hereth, TU Darmstadt;
+ definition of \url moved \AtBeginDocument
+ (allows for url package of Donald Arseneau),
+ suggested by Manfred Hauswirth, TU of Vienna;
+ \large for part entries in the TOC
+
+16.04.00 llncs.cls 2.8 new option "orivec" to preserve the original
+ vector definition, read "arrow" accent
+
+17.01.01 llncs.cls 2.9 hardwired texts made polyglot,
+ available languages: english (default),
+ french, german - all are "babel-proof"
+
+20.06.01 splncs.bst public release of a BibTeX style for LNCS,
+ nobly provided by Jason Noble
+
+14.08.01 llncs.cls 2.10 TOC: authors flushleft,
+ entries without hyphenation; suggested
+ by Wiro Niessen, Imaging Center - Utrecht
+
+23.01.02 llncs.cls 2.11 fixed footnote number confusion with
+ \thanks, numbered institutes, and normal
+ footnote entries; error reported by
+ Saverio Cittadini, Istituto Tecnico
+ Industriale "Tito Sarrocchi" - Siena
+
+28.01.02 llncs.cls 2.12 fixed footnote fix; error reported by
+ Chris Mesterharm, CS Dept. Rutgers - NJ
+
+28.01.02 llncs.cls 2.13 fixed the fix (programmer needs vacation)
+
+17.08.04 llncs.cls 2.14 TOC: authors indented, smart \and handling
+ for the TOC suggested by Thomas Gabel
+ University of Osnabrueck
+
+07.03.06 splncs.bst fix for BibTeX entries without year; patch
+ provided by Jerry James, Utah State University
+
+14.06.06 splncs_srt.bst a sorting BibTeX style for LNCS, feature
+ provided by Tobias Heindel, FMI Uni-Stuttgart
+
+16.10.06 llncs.dem 2.3 removed affiliations from \tocauthor demo
+
+11.12.07 llncs.doc note on online visibility of given e-mail address
+
+15.06.09 splncs03.bst new BibTeX style compliant with the current
+ requirements, provided by Maurizio "Titto"
+ Patrignani of Universita' Roma Tre
+
+30.03.10 llncs.cls 2.15 fixed broken hyperref interoperability;
+ patch provided by Sven Koehler,
+ Hamburg University of Technology
+
+15.04.10 llncs.cls 2.16 fixed hyperref warning for informatory TOC entries;
+ introduced \keywords command - finally;
+ blank removed from \keywordname, flaw reported
+ by Armin B. Wagner, IGW TU Vienna
+
+15.04.10 llncs.cls 2.17 fixed missing switch "openright" used by \backmatter;
+ flaw reported by Tobias Pape, University of Potsdam
+
+27.09.13 llncs.cls 2.18 fixed "ngerman" incompatibility; solution provided
+ by Bastian Pfleging, University of Stuttgart
+
+04.09.17 llncs.cls 2.19 introduced \orcidID command
+
+10.03.18 llncs.cls 2.20 adjusted \doi according to CrossRef requirements;
+ TOC: removed affiliation numbers
+
+ splncs04.bst added doi field;
+ bold journal numbers
+
+ samplepaper.tex new sample paper
+
+ llncsdoc.pdf new LaTeX class documentation
+
+12.01.22 llncs.cls 2.21 fixed German and French \maketitle, bug reported by
+ Alexander Malkis, Technical University of Munich;
+ use detokenized argument in the definition of \doi
+ to allow underscores in DOIs
diff --git a/macros/latex/contrib/llncs/llncs.cls b/macros/latex/contrib/llncs/llncs.cls
new file mode 100644
index 0000000000..075d73327c
--- /dev/null
+++ b/macros/latex/contrib/llncs/llncs.cls
@@ -0,0 +1,1218 @@
+% LLNCS DOCUMENT CLASS -- version 2.21 (12-Jan-2022)
+% Springer Verlag LaTeX2e support for Lecture Notes in Computer Science
+%
+%%
+%% \CharacterTable
+%% {Upper-case \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
+%% Lower-case \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
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]
+\ProvidesClass{llncs}[2022/01/12 v2.21
+^^J LaTeX document class for Lecture Notes in Computer Science]
+% Options
+\let\if@envcntreset\iffalse
+\DeclareOption{envcountreset}{\let\if@envcntreset\iftrue}
+\DeclareOption{citeauthoryear}{\let\citeauthoryear=Y}
+\DeclareOption{oribibl}{\let\oribibl=Y}
+\let\if@custvec\iftrue
+\DeclareOption{orivec}{\let\if@custvec\iffalse}
+\let\if@envcntsame\iffalse
+\DeclareOption{envcountsame}{\let\if@envcntsame\iftrue}
+\let\if@envcntsect\iffalse
+\DeclareOption{envcountsect}{\let\if@envcntsect\iftrue}
+\let\if@runhead\iffalse
+\DeclareOption{runningheads}{\let\if@runhead\iftrue}
+
+\let\if@openright\iftrue
+\let\if@openbib\iffalse
+\DeclareOption{openbib}{\let\if@openbib\iftrue}
+
+% languages
+\let\switcht@@therlang\relax
+\def\ds@deutsch{\def\switcht@@therlang{\switcht@deutsch}}
+\def\ds@francais{\def\switcht@@therlang{\switcht@francais}}
+
+\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
+
+\ProcessOptions
+
+\LoadClass[twoside]{article}
+\RequirePackage{multicol} % needed for the list of participants, index
+\RequirePackage{aliascnt}
+
+\setlength{\textwidth}{12.2cm}
+\setlength{\textheight}{19.3cm}
+\renewcommand\@pnumwidth{2em}
+\renewcommand\@tocrmarg{3.5em}
+%
+\def\@dottedtocline#1#2#3#4#5{%
+ \ifnum #1>\c@tocdepth \else
+ \vskip \z@ \@plus.2\p@
+ {\leftskip #2\relax \rightskip \@tocrmarg \advance\rightskip by 0pt plus 2cm
+ \parfillskip -\rightskip \pretolerance=10000
+ \parindent #2\relax\@afterindenttrue
+ \interlinepenalty\@M
+ \leavevmode
+ \@tempdima #3\relax
+ \advance\leftskip \@tempdima \null\nobreak\hskip -\leftskip
+ {#4}\nobreak
+ \leaders\hbox{$\m@th
+ \mkern \@dotsep mu\hbox{.}\mkern \@dotsep
+ mu$}\hfill
+ \nobreak
+ \hb@xt@\@pnumwidth{\hfil\normalfont \normalcolor #5}%
+ \par}%
+ \fi}
+%
+\def\switcht@albion{%
+\def\abstractname{Abstract.}
+\def\ackname{Acknowledgement.}
+\def\andname{and}
+\def\lastandname{\unskip, and}
+\def\appendixname{Appendix}
+\def\chaptername{Chapter}
+\def\claimname{Claim}
+\def\conjecturename{Conjecture}
+\def\contentsname{Table of Contents}
+\def\corollaryname{Corollary}
+\def\definitionname{Definition}
+\def\examplename{Example}
+\def\exercisename{Exercise}
+\def\figurename{Fig.}
+\def\keywordname{{\bf Keywords:}}
+\def\indexname{Index}
+\def\lemmaname{Lemma}
+\def\contriblistname{List of Contributors}
+\def\listfigurename{List of Figures}
+\def\listtablename{List of Tables}
+\def\mailname{{\it Correspondence to\/}:}
+\def\noteaddname{Note added in proof}
+\def\notename{Note}
+\def\partname{Part}
+\def\problemname{Problem}
+\def\proofname{Proof}
+\def\propertyname{Property}
+\def\propositionname{Proposition}
+\def\questionname{Question}
+\def\remarkname{Remark}
+\def\seename{see}
+\def\solutionname{Solution}
+\def\subclassname{{\it Subject Classifications\/}:}
+\def\tablename{Table}
+\def\theoremname{Theorem}}
+\switcht@albion
+% Names of theorem like environments are already defined
+% but must be translated if another language is chosen
+%
+% French section
+\def\switcht@francais{%\typeout{On parle francais.}%
+ \def\abstractname{R\'esum\'e.}%
+ \def\ackname{Remerciements.}%
+ \def\andname{et}%
+ \def\lastandname{ et}%
+ \def\appendixname{Appendice}%
+ \def\chaptername{Chapitre}%
+ \def\claimname{Pr\'etention}%
+ \def\conjecturename{Hypoth\`ese}%
+ \def\contentsname{Table des mati\`eres}%
+ \def\corollaryname{Corollaire}%
+ \def\definitionname{D\'efinition}%
+ \def\examplename{Exemple}%
+ \def\exercisename{Exercice}%
+ \def\figurename{Fig.}%
+ \def\keywordname{{\bf Mots-cl\'e:}}%
+ \def\indexname{Index}%
+ \def\lemmaname{Lemme}%
+ \def\contriblistname{Liste des contributeurs}%
+ \def\listfigurename{Liste des figures}%
+ \def\listtablename{Liste des tables}%
+ \def\mailname{{\it Correspondence to\/}:}%
+ \def\noteaddname{Note ajout\'ee \`a l'\'epreuve}%
+ \def\notename{Remarque}%
+ \def\partname{Partie}%
+ \def\problemname{Probl\`eme}%
+ \def\proofname{Preuve}%
+ \def\propertyname{Caract\'eristique}%
+%\def\propositionname{Proposition}%
+ \def\questionname{Question}%
+ \def\remarkname{Remarque}%
+ \def\seename{voir}%
+ \def\solutionname{Solution}%
+ \def\subclassname{{\it Subject Classifications\/}:}%
+ \def\tablename{Tableau}%
+ \def\theoremname{Th\'eor\`eme}%
+}
+%
+% German section
+\def\switcht@deutsch{%\typeout{Man spricht deutsch.}%
+ \def\abstractname{Zusammenfassung.}%
+ \def\ackname{Danksagung.}%
+ \def\andname{und}%
+ \def\lastandname{ und}%
+ \def\appendixname{Anhang}%
+ \def\chaptername{Kapitel}%
+ \def\claimname{Behauptung}%
+ \def\conjecturename{Hypothese}%
+ \def\contentsname{Inhaltsverzeichnis}%
+ \def\corollaryname{Korollar}%
+%\def\definitionname{Definition}%
+ \def\examplename{Beispiel}%
+ \def\exercisename{\"Ubung}%
+ \def\figurename{Abb.}%
+ \def\keywordname{{\bf Schl\"usselw\"orter:}}%
+ \def\indexname{Index}%
+%\def\lemmaname{Lemma}%
+ \def\contriblistname{Mitarbeiter}%
+ \def\listfigurename{Abbildungsverzeichnis}%
+ \def\listtablename{Tabellenverzeichnis}%
+ \def\mailname{{\it Correspondence to\/}:}%
+ \def\noteaddname{Nachtrag}%
+ \def\notename{Anmerkung}%
+ \def\partname{Teil}%
+%\def\problemname{Problem}%
+ \def\proofname{Beweis}%
+ \def\propertyname{Eigenschaft}%
+%\def\propositionname{Proposition}%
+ \def\questionname{Frage}%
+ \def\remarkname{Anmerkung}%
+ \def\seename{siehe}%
+ \def\solutionname{L\"osung}%
+ \def\subclassname{{\it Subject Classifications\/}:}%
+ \def\tablename{Tabelle}%
+%\def\theoremname{Theorem}%
+}
+
+% Ragged bottom for the actual page
+\def\thisbottomragged{\def\@textbottom{\vskip\z@ plus.0001fil
+\global\let\@textbottom\relax}}
+
+\renewcommand\small{%
+ \@setfontsize\small\@ixpt{11}%
+ \abovedisplayskip 8.5\p@ \@plus3\p@ \@minus4\p@
+ \abovedisplayshortskip \z@ \@plus2\p@
+ \belowdisplayshortskip 4\p@ \@plus2\p@ \@minus2\p@
+ \def\@listi{\leftmargin\leftmargini
+ \parsep 0\p@ \@plus1\p@ \@minus\p@
+ \topsep 8\p@ \@plus2\p@ \@minus4\p@
+ \itemsep0\p@}%
+ \belowdisplayskip \abovedisplayskip
+}
+
+\frenchspacing
+\widowpenalty=10000
+\clubpenalty=10000
+
+\setlength\oddsidemargin {63\p@}
+\setlength\evensidemargin {63\p@}
+\setlength\marginparwidth {90\p@}
+
+\setlength\headsep {16\p@}
+
+\setlength\footnotesep{7.7\p@}
+\setlength\textfloatsep{8mm\@plus 2\p@ \@minus 4\p@}
+\setlength\intextsep {8mm\@plus 2\p@ \@minus 2\p@}
+
+\setcounter{secnumdepth}{2}
+
+\newcounter {chapter}
+\renewcommand\thechapter {\@arabic\c@chapter}
+
+\newif\if@mainmatter \@mainmattertrue
+\newcommand\frontmatter{\cleardoublepage
+ \@mainmatterfalse\pagenumbering{Roman}}
+\newcommand\mainmatter{\cleardoublepage
+ \@mainmattertrue\pagenumbering{arabic}}
+\newcommand\backmatter{\if@openright\cleardoublepage\else\clearpage\fi
+ \@mainmatterfalse}
+
+\renewcommand\part{\cleardoublepage
+ \thispagestyle{empty}%
+ \if@twocolumn
+ \onecolumn
+ \@tempswatrue
+ \else
+ \@tempswafalse
+ \fi
+ \null\vfil
+ \secdef\@part\@spart}
+
+\def\@part[#1]#2{%
+ \ifnum \c@secnumdepth >-2\relax
+ \refstepcounter{part}%
+ \addcontentsline{toc}{part}{\thepart\hspace{1em}#1}%
+ \else
+ \addcontentsline{toc}{part}{#1}%
+ \fi
+ \markboth{}{}%
+ {\centering
+ \interlinepenalty \@M
+ \normalfont
+ \ifnum \c@secnumdepth >-2\relax
+ \huge\bfseries \partname~\thepart
+ \par
+ \vskip 20\p@
+ \fi
+ \Huge \bfseries #2\par}%
+ \@endpart}
+\def\@spart#1{%
+ {\centering
+ \interlinepenalty \@M
+ \normalfont
+ \Huge \bfseries #1\par}%
+ \@endpart}
+\def\@endpart{\vfil\newpage
+ \if@twoside
+ \null
+ \thispagestyle{empty}%
+ \newpage
+ \fi
+ \if@tempswa
+ \twocolumn
+ \fi}
+
+\newcommand\chapter{\clearpage
+ \thispagestyle{empty}%
+ \global\@topnum\z@
+ \@afterindentfalse
+ \secdef\@chapter\@schapter}
+\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne
+ \if@mainmatter
+ \refstepcounter{chapter}%
+ \typeout{\@chapapp\space\thechapter.}%
+ \addcontentsline{toc}{chapter}%
+ {\protect\numberline{\thechapter}#1}%
+ \else
+ \addcontentsline{toc}{chapter}{#1}%
+ \fi
+ \else
+ \addcontentsline{toc}{chapter}{#1}%
+ \fi
+ \chaptermark{#1}%
+ \addtocontents{lof}{\protect\addvspace{10\p@}}%
+ \addtocontents{lot}{\protect\addvspace{10\p@}}%
+ \if@twocolumn
+ \@topnewpage[\@makechapterhead{#2}]%
+ \else
+ \@makechapterhead{#2}%
+ \@afterheading
+ \fi}
+\def\@makechapterhead#1{%
+% \vspace*{50\p@}%
+ {\centering
+ \ifnum \c@secnumdepth >\m@ne
+ \if@mainmatter
+ \large\bfseries \@chapapp{} \thechapter
+ \par\nobreak
+ \vskip 20\p@
+ \fi
+ \fi
+ \interlinepenalty\@M
+ \Large \bfseries #1\par\nobreak
+ \vskip 40\p@
+ }}
+\def\@schapter#1{\if@twocolumn
+ \@topnewpage[\@makeschapterhead{#1}]%
+ \else
+ \@makeschapterhead{#1}%
+ \@afterheading
+ \fi}
+\def\@makeschapterhead#1{%
+% \vspace*{50\p@}%
+ {\centering
+ \normalfont
+ \interlinepenalty\@M
+ \Large \bfseries #1\par\nobreak
+ \vskip 40\p@
+ }}
+
+\renewcommand\section{\@startsection{section}{1}{\z@}%
+ {-18\p@ \@plus -4\p@ \@minus -4\p@}%
+ {12\p@ \@plus 4\p@ \@minus 4\p@}%
+ {\normalfont\large\bfseries\boldmath
+ \rightskip=\z@ \@plus 8em\pretolerance=10000 }}
+\renewcommand\subsection{\@startsection{subsection}{2}{\z@}%
+ {-18\p@ \@plus -4\p@ \@minus -4\p@}%
+ {8\p@ \@plus 4\p@ \@minus 4\p@}%
+ {\normalfont\normalsize\bfseries\boldmath
+ \rightskip=\z@ \@plus 8em\pretolerance=10000 }}
+\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%
+ {-18\p@ \@plus -4\p@ \@minus -4\p@}%
+ {-0.5em \@plus -0.22em \@minus -0.1em}%
+ {\normalfont\normalsize\bfseries\boldmath}}
+\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
+ {-12\p@ \@plus -4\p@ \@minus -4\p@}%
+ {-0.5em \@plus -0.22em \@minus -0.1em}%
+ {\normalfont\normalsize\itshape}}
+\renewcommand\subparagraph[1]{\typeout{LLNCS warning: You should not use
+ \string\subparagraph\space with this class}\vskip0.5cm
+You should not use \verb|\subparagraph| with this class.\vskip0.5cm}
+
+\DeclareMathSymbol{\Gamma}{\mathalpha}{letters}{"00}
+\DeclareMathSymbol{\Delta}{\mathalpha}{letters}{"01}
+\DeclareMathSymbol{\Theta}{\mathalpha}{letters}{"02}
+\DeclareMathSymbol{\Lambda}{\mathalpha}{letters}{"03}
+\DeclareMathSymbol{\Xi}{\mathalpha}{letters}{"04}
+\DeclareMathSymbol{\Pi}{\mathalpha}{letters}{"05}
+\DeclareMathSymbol{\Sigma}{\mathalpha}{letters}{"06}
+\DeclareMathSymbol{\Upsilon}{\mathalpha}{letters}{"07}
+\DeclareMathSymbol{\Phi}{\mathalpha}{letters}{"08}
+\DeclareMathSymbol{\Psi}{\mathalpha}{letters}{"09}
+\DeclareMathSymbol{\Omega}{\mathalpha}{letters}{"0A}
+
+\let\footnotesize\small
+
+\if@custvec
+\def\vec#1{\mathchoice{\mbox{\boldmath$\displaystyle#1$}}
+{\mbox{\boldmath$\textstyle#1$}}
+{\mbox{\boldmath$\scriptstyle#1$}}
+{\mbox{\boldmath$\scriptscriptstyle#1$}}}
+\fi
+
+\def\squareforqed{\hbox{\rlap{$\sqcap$}$\sqcup$}}
+\def\qed{\ifmmode\squareforqed\else{\unskip\nobreak\hfil
+\penalty50\hskip1em\null\nobreak\hfil\squareforqed
+\parfillskip=0pt\finalhyphendemerits=0\endgraf}\fi}
+
+\def\getsto{\mathrel{\mathchoice {\vcenter{\offinterlineskip
+\halign{\hfil
+$\displaystyle##$\hfil\cr\gets\cr\to\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr\gets
+\cr\to\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr\gets
+\cr\to\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr
+\gets\cr\to\cr}}}}}
+\def\lid{\mathrel{\mathchoice {\vcenter{\offinterlineskip\halign{\hfil
+$\displaystyle##$\hfil\cr<\cr\noalign{\vskip1.2pt}=\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr<\cr
+\noalign{\vskip1.2pt}=\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr<\cr
+\noalign{\vskip1pt}=\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr
+<\cr
+\noalign{\vskip0.9pt}=\cr}}}}}
+\def\gid{\mathrel{\mathchoice {\vcenter{\offinterlineskip\halign{\hfil
+$\displaystyle##$\hfil\cr>\cr\noalign{\vskip1.2pt}=\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr>\cr
+\noalign{\vskip1.2pt}=\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr>\cr
+\noalign{\vskip1pt}=\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr
+>\cr
+\noalign{\vskip0.9pt}=\cr}}}}}
+\def\grole{\mathrel{\mathchoice {\vcenter{\offinterlineskip
+\halign{\hfil
+$\displaystyle##$\hfil\cr>\cr\noalign{\vskip-1pt}<\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\textstyle##$\hfil\cr
+>\cr\noalign{\vskip-1pt}<\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptstyle##$\hfil\cr
+>\cr\noalign{\vskip-0.8pt}<\cr}}}
+{\vcenter{\offinterlineskip\halign{\hfil$\scriptscriptstyle##$\hfil\cr
+>\cr\noalign{\vskip-0.3pt}<\cr}}}}}
+\def\bbbr{{\rm I\!R}} %reelle Zahlen
+\def\bbbm{{\rm I\!M}}
+\def\bbbn{{\rm I\!N}} %natuerliche Zahlen
+\def\bbbf{{\rm I\!F}}
+\def\bbbh{{\rm I\!H}}
+\def\bbbk{{\rm I\!K}}
+\def\bbbp{{\rm I\!P}}
+\def\bbbone{{\mathchoice {\rm 1\mskip-4mu l} {\rm 1\mskip-4mu l}
+{\rm 1\mskip-4.5mu l} {\rm 1\mskip-5mu l}}}
+\def\bbbc{{\mathchoice {\setbox0=\hbox{$\displaystyle\rm C$}\hbox{\hbox
+to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}
+{\setbox0=\hbox{$\textstyle\rm C$}\hbox{\hbox
+to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptstyle\rm C$}\hbox{\hbox
+to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptscriptstyle\rm C$}\hbox{\hbox
+to0pt{\kern0.4\wd0\vrule height0.9\ht0\hss}\box0}}}}
+\def\bbbq{{\mathchoice {\setbox0=\hbox{$\displaystyle\rm
+Q$}\hbox{\raise
+0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.8\ht0\hss}\box0}}
+{\setbox0=\hbox{$\textstyle\rm Q$}\hbox{\raise
+0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.8\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptstyle\rm Q$}\hbox{\raise
+0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.7\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptscriptstyle\rm Q$}\hbox{\raise
+0.15\ht0\hbox to0pt{\kern0.4\wd0\vrule height0.7\ht0\hss}\box0}}}}
+\def\bbbt{{\mathchoice {\setbox0=\hbox{$\displaystyle\rm
+T$}\hbox{\hbox to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}
+{\setbox0=\hbox{$\textstyle\rm T$}\hbox{\hbox
+to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptstyle\rm T$}\hbox{\hbox
+to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptscriptstyle\rm T$}\hbox{\hbox
+to0pt{\kern0.3\wd0\vrule height0.9\ht0\hss}\box0}}}}
+\def\bbbs{{\mathchoice
+{\setbox0=\hbox{$\displaystyle \rm S$}\hbox{\raise0.5\ht0\hbox
+to0pt{\kern0.35\wd0\vrule height0.45\ht0\hss}\hbox
+to0pt{\kern0.55\wd0\vrule height0.5\ht0\hss}\box0}}
+{\setbox0=\hbox{$\textstyle \rm S$}\hbox{\raise0.5\ht0\hbox
+to0pt{\kern0.35\wd0\vrule height0.45\ht0\hss}\hbox
+to0pt{\kern0.55\wd0\vrule height0.5\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptstyle \rm S$}\hbox{\raise0.5\ht0\hbox
+to0pt{\kern0.35\wd0\vrule height0.45\ht0\hss}\raise0.05\ht0\hbox
+to0pt{\kern0.5\wd0\vrule height0.45\ht0\hss}\box0}}
+{\setbox0=\hbox{$\scriptscriptstyle\rm S$}\hbox{\raise0.5\ht0\hbox
+to0pt{\kern0.4\wd0\vrule height0.45\ht0\hss}\raise0.05\ht0\hbox
+to0pt{\kern0.55\wd0\vrule height0.45\ht0\hss}\box0}}}}
+\def\bbbz{{\mathchoice {\hbox{$\mathsf\textstyle Z\kern-0.4em Z$}}
+{\hbox{$\mathsf\textstyle Z\kern-0.4em Z$}}
+{\hbox{$\mathsf\scriptstyle Z\kern-0.3em Z$}}
+{\hbox{$\mathsf\scriptscriptstyle Z\kern-0.2em Z$}}}}
+
+\let\ts\,
+
+\setlength\leftmargini {17\p@}
+\setlength\leftmargin {\leftmargini}
+\setlength\leftmarginii {\leftmargini}
+\setlength\leftmarginiii {\leftmargini}
+\setlength\leftmarginiv {\leftmargini}
+\setlength \labelsep {.5em}
+\setlength \labelwidth{\leftmargini}
+\addtolength\labelwidth{-\labelsep}
+
+\def\@listI{\leftmargin\leftmargini
+ \parsep 0\p@ \@plus1\p@ \@minus\p@
+ \topsep 8\p@ \@plus2\p@ \@minus4\p@
+ \itemsep0\p@}
+\let\@listi\@listI
+\@listi
+\def\@listii {\leftmargin\leftmarginii
+ \labelwidth\leftmarginii
+ \advance\labelwidth-\labelsep
+ \topsep 0\p@ \@plus2\p@ \@minus\p@}
+\def\@listiii{\leftmargin\leftmarginiii
+ \labelwidth\leftmarginiii
+ \advance\labelwidth-\labelsep
+ \topsep 0\p@ \@plus\p@\@minus\p@
+ \parsep \z@
+ \partopsep \p@ \@plus\z@ \@minus\p@}
+
+\renewcommand\labelitemi{\normalfont\bfseries --}
+\renewcommand\labelitemii{$\m@th\bullet$}
+
+\setlength\arraycolsep{1.4\p@}
+\setlength\tabcolsep{1.4\p@}
+
+\def\tableofcontents{\chapter*{\contentsname\@mkboth{{\contentsname}}%
+ {{\contentsname}}}
+ \def\authcount##1{\setcounter{auco}{##1}\setcounter{@auth}{1}}
+ \def\lastand{\ifnum\value{auco}=2\relax
+ \unskip{} \andname\
+ \else
+ \unskip \lastandname\
+ \fi}%
+ \def\and{\stepcounter{@auth}\relax
+ \ifnum\value{@auth}=\value{auco}%
+ \lastand
+ \else
+ \unskip,
+ \fi}%
+ \@starttoc{toc}\if@restonecol\twocolumn\fi}
+
+\def\l@part#1#2{\addpenalty{\@secpenalty}%
+ \addvspace{2em plus\p@}% % space above part line
+ \begingroup
+ \parindent \z@
+ \rightskip \z@ plus 5em
+ \hrule\vskip5pt
+ \large % same size as for a contribution heading
+ \bfseries\boldmath % set line in boldface
+ \leavevmode % TeX command to enter horizontal mode.
+ #1\par
+ \vskip5pt
+ \hrule
+ \vskip1pt
+ \nobreak % Never break after part entry
+ \endgroup}
+
+\def\@dotsep{2}
+
+\let\phantomsection=\relax
+
+\def\hyperhrefextend{\ifx\hyper@anchor\@undefined\else
+{}\fi}
+
+\def\addnumcontentsmark#1#2#3{%
+\addtocontents{#1}{\protect\contentsline{#2}{\protect\numberline
+ {\thechapter}#3}{\thepage}\hyperhrefextend}}%
+\def\addcontentsmark#1#2#3{%
+\addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}\hyperhrefextend}}%
+\def\addcontentsmarkwop#1#2#3{%
+\addtocontents{#1}{\protect\contentsline{#2}{#3}{0}\hyperhrefextend}}%
+
+\def\@adcmk[#1]{\ifcase #1 \or
+\def\@gtempa{\addnumcontentsmark}%
+ \or \def\@gtempa{\addcontentsmark}%
+ \or \def\@gtempa{\addcontentsmarkwop}%
+ \fi\@gtempa{toc}{chapter}%
+}
+\def\addtocmark{%
+\phantomsection
+\@ifnextchar[{\@adcmk}{\@adcmk[3]}%
+}
+
+\def\l@chapter#1#2{\addpenalty{-\@highpenalty}
+ \vskip 1.0em plus 1pt \@tempdima 1.5em \begingroup
+ \parindent \z@ \rightskip \@tocrmarg
+ \advance\rightskip by 0pt plus 2cm
+ \parfillskip -\rightskip \pretolerance=10000
+ \leavevmode \advance\leftskip\@tempdima \hskip -\leftskip
+ {\large\bfseries\boldmath#1}\ifx0#2\hfil\null
+ \else
+ \nobreak
+ \leaders\hbox{$\m@th \mkern \@dotsep mu.\mkern
+ \@dotsep mu$}\hfill
+ \nobreak\hbox to\@pnumwidth{\hss #2}%
+ \fi\par
+ \penalty\@highpenalty \endgroup}
+
+\def\l@title#1#2{\addpenalty{-\@highpenalty}
+ \addvspace{8pt plus 1pt}
+ \@tempdima \z@
+ \begingroup
+ \parindent \z@ \rightskip \@tocrmarg
+ \advance\rightskip by 0pt plus 2cm
+ \parfillskip -\rightskip \pretolerance=10000
+ \leavevmode \advance\leftskip\@tempdima \hskip -\leftskip
+ #1\nobreak
+ \leaders\hbox{$\m@th \mkern \@dotsep mu.\mkern
+ \@dotsep mu$}\hfill
+ \nobreak\hbox to\@pnumwidth{\hss #2}\par
+ \penalty\@highpenalty \endgroup}
+
+\def\l@author#1#2{\addpenalty{\@highpenalty}
+ \@tempdima=15\p@ %\z@
+ \begingroup
+ \parindent \z@ \rightskip \@tocrmarg
+ \advance\rightskip by 0pt plus 2cm
+ \pretolerance=10000
+ \leavevmode \advance\leftskip\@tempdima %\hskip -\leftskip
+ \textit{#1}\par
+ \penalty\@highpenalty \endgroup}
+
+\setcounter{tocdepth}{0}
+\newdimen\tocchpnum
+\newdimen\tocsecnum
+\newdimen\tocsectotal
+\newdimen\tocsubsecnum
+\newdimen\tocsubsectotal
+\newdimen\tocsubsubsecnum
+\newdimen\tocsubsubsectotal
+\newdimen\tocparanum
+\newdimen\tocparatotal
+\newdimen\tocsubparanum
+\tocchpnum=\z@ % no chapter numbers
+\tocsecnum=15\p@ % section 88. plus 2.222pt
+\tocsubsecnum=23\p@ % subsection 88.8 plus 2.222pt
+\tocsubsubsecnum=27\p@ % subsubsection 88.8.8 plus 1.444pt
+\tocparanum=35\p@ % paragraph 88.8.8.8 plus 1.666pt
+\tocsubparanum=43\p@ % subparagraph 88.8.8.8.8 plus 1.888pt
+\def\calctocindent{%
+\tocsectotal=\tocchpnum
+\advance\tocsectotal by\tocsecnum
+\tocsubsectotal=\tocsectotal
+\advance\tocsubsectotal by\tocsubsecnum
+\tocsubsubsectotal=\tocsubsectotal
+\advance\tocsubsubsectotal by\tocsubsubsecnum
+\tocparatotal=\tocsubsubsectotal
+\advance\tocparatotal by\tocparanum}
+\calctocindent
+
+\def\l@section{\@dottedtocline{1}{\tocchpnum}{\tocsecnum}}
+\def\l@subsection{\@dottedtocline{2}{\tocsectotal}{\tocsubsecnum}}
+\def\l@subsubsection{\@dottedtocline{3}{\tocsubsectotal}{\tocsubsubsecnum}}
+\def\l@paragraph{\@dottedtocline{4}{\tocsubsubsectotal}{\tocparanum}}
+\def\l@subparagraph{\@dottedtocline{5}{\tocparatotal}{\tocsubparanum}}
+
+\def\listoffigures{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn
+ \fi\section*{\listfigurename\@mkboth{{\listfigurename}}{{\listfigurename}}}
+ \@starttoc{lof}\if@restonecol\twocolumn\fi}
+\def\l@figure{\@dottedtocline{1}{0em}{1.5em}}
+
+\def\listoftables{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn
+ \fi\section*{\listtablename\@mkboth{{\listtablename}}{{\listtablename}}}
+ \@starttoc{lot}\if@restonecol\twocolumn\fi}
+\let\l@table\l@figure
+
+\renewcommand\listoffigures{%
+ \section*{\listfigurename
+ \@mkboth{\listfigurename}{\listfigurename}}%
+ \@starttoc{lof}%
+ }
+
+\renewcommand\listoftables{%
+ \section*{\listtablename
+ \@mkboth{\listtablename}{\listtablename}}%
+ \@starttoc{lot}%
+ }
+
+\ifx\oribibl\undefined
+\ifx\citeauthoryear\undefined
+\renewenvironment{thebibliography}[1]
+ {\section*{\refname}
+ \def\@biblabel##1{##1.}
+ \small
+ \list{\@biblabel{\@arabic\c@enumiv}}%
+ {\settowidth\labelwidth{\@biblabel{#1}}%
+ \leftmargin\labelwidth
+ \advance\leftmargin\labelsep
+ \if@openbib
+ \advance\leftmargin\bibindent
+ \itemindent -\bibindent
+ \listparindent \itemindent
+ \parsep \z@
+ \fi
+ \usecounter{enumiv}%
+ \let\p@enumiv\@empty
+ \renewcommand\theenumiv{\@arabic\c@enumiv}}%
+ \if@openbib
+ \renewcommand\newblock{\par}%
+ \else
+ \renewcommand\newblock{\hskip .11em \@plus.33em \@minus.07em}%
+ \fi
+ \sloppy\clubpenalty4000\widowpenalty4000%
+ \sfcode`\.=\@m}
+ {\def\@noitemerr
+ {\@latex@warning{Empty `thebibliography' environment}}%
+ \endlist}
+\def\@lbibitem[#1]#2{\item[{[#1]}\hfill]\if@filesw
+ {\let\protect\noexpand\immediate
+ \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces}
+\newcount\@tempcntc
+\def\@citex[#1]#2{\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi
+ \@tempcnta\z@\@tempcntb\m@ne\def\@citea{}\@cite{\@for\@citeb:=#2\do
+ {\@ifundefined
+ {b@\@citeb}{\@citeo\@tempcntb\m@ne\@citea\def\@citea{,}{\bfseries
+ ?}\@warning
+ {Citation `\@citeb' on page \thepage \space undefined}}%
+ {\setbox\z@\hbox{\global\@tempcntc0\csname b@\@citeb\endcsname\relax}%
+ \ifnum\@tempcntc=\z@ \@citeo\@tempcntb\m@ne
+ \@citea\def\@citea{,}\hbox{\csname b@\@citeb\endcsname}%
+ \else
+ \advance\@tempcntb\@ne
+ \ifnum\@tempcntb=\@tempcntc
+ \else\advance\@tempcntb\m@ne\@citeo
+ \@tempcnta\@tempcntc\@tempcntb\@tempcntc\fi\fi}}\@citeo}{#1}}
+\def\@citeo{\ifnum\@tempcnta>\@tempcntb\else
+ \@citea\def\@citea{,\,\hskip\z@skip}%
+ \ifnum\@tempcnta=\@tempcntb\the\@tempcnta\else
+ {\advance\@tempcnta\@ne\ifnum\@tempcnta=\@tempcntb \else
+ \def\@citea{--}\fi
+ \advance\@tempcnta\m@ne\the\@tempcnta\@citea\the\@tempcntb}\fi\fi}
+\else
+\renewenvironment{thebibliography}[1]
+ {\section*{\refname}
+ \small
+ \list{}%
+ {\settowidth\labelwidth{}%
+ \leftmargin\parindent
+ \itemindent=-\parindent
+ \labelsep=\z@
+ \if@openbib
+ \advance\leftmargin\bibindent
+ \itemindent -\bibindent
+ \listparindent \itemindent
+ \parsep \z@
+ \fi
+ \usecounter{enumiv}%
+ \let\p@enumiv\@empty
+ \renewcommand\theenumiv{}}%
+ \if@openbib
+ \renewcommand\newblock{\par}%
+ \else
+ \renewcommand\newblock{\hskip .11em \@plus.33em \@minus.07em}%
+ \fi
+ \sloppy\clubpenalty4000\widowpenalty4000%
+ \sfcode`\.=\@m}
+ {\def\@noitemerr
+ {\@latex@warning{Empty `thebibliography' environment}}%
+ \endlist}
+ \def\@cite#1{#1}%
+ \def\@lbibitem[#1]#2{\item[]\if@filesw
+ {\def\protect##1{\string ##1\space}\immediate
+ \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces}
+ \fi
+\else
+\@cons\@openbib@code{\noexpand\small}
+\fi
+
+\def\idxquad{\hskip 10\p@}% space that divides entry from number
+
+\def\@idxitem{\par\hangindent 10\p@}
+
+\def\subitem{\par\setbox0=\hbox{--\enspace}% second order
+ \noindent\hangindent\wd0\box0}% index entry
+
+\def\subsubitem{\par\setbox0=\hbox{--\,--\enspace}% third
+ \noindent\hangindent\wd0\box0}% order index entry
+
+\def\indexspace{\par \vskip 10\p@ plus5\p@ minus3\p@\relax}
+
+\renewenvironment{theindex}
+ {\@mkboth{\indexname}{\indexname}%
+ \thispagestyle{empty}\parindent\z@
+ \parskip\z@ \@plus .3\p@\relax
+ \let\item\par
+ \def\,{\relax\ifmmode\mskip\thinmuskip
+ \else\hskip0.2em\ignorespaces\fi}%
+ \normalfont\small
+ \begin{multicols}{2}[\@makeschapterhead{\indexname}]%
+ }
+ {\end{multicols}}
+
+\renewcommand\footnoterule{%
+ \kern-3\p@
+ \hrule\@width 2truecm
+ \kern2.6\p@}
+ \newdimen\fnindent
+ \fnindent1em
+\long\def\@makefntext#1{%
+ \parindent \fnindent%
+ \leftskip \fnindent%
+ \noindent
+ \llap{\hb@xt@1em{\hss\@makefnmark\ }}\ignorespaces#1}
+
+\long\def\@makecaption#1#2{%
+ \small
+ \vskip\abovecaptionskip
+ \sbox\@tempboxa{{\bfseries #1.} #2}%
+ \ifdim \wd\@tempboxa >\hsize
+ {\bfseries #1.} #2\par
+ \else
+ \global \@minipagefalse
+ \hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%
+ \fi
+ \vskip\belowcaptionskip}
+
+\def\fps@figure{htbp}
+\def\fnum@figure{\figurename\thinspace\thefigure}
+\def \@floatboxreset {%
+ \reset@font
+ \small
+ \@setnobreak
+ \@setminipage
+}
+\def\fps@table{htbp}
+\def\fnum@table{\tablename~\thetable}
+\renewenvironment{table}
+ {\setlength\abovecaptionskip{0\p@}%
+ \setlength\belowcaptionskip{10\p@}%
+ \@float{table}}
+ {\end@float}
+\renewenvironment{table*}
+ {\setlength\abovecaptionskip{0\p@}%
+ \setlength\belowcaptionskip{10\p@}%
+ \@dblfloat{table}}
+ {\end@dblfloat}
+
+\long\def\@caption#1[#2]#3{\par\addcontentsline{\csname
+ ext@#1\endcsname}{#1}{\protect\numberline{\csname
+ the#1\endcsname}{\ignorespaces #2}}\begingroup
+ \@parboxrestore
+ \@makecaption{\csname fnum@#1\endcsname}{\ignorespaces #3}\par
+ \endgroup}
+
+% LaTeX does not provide a command to enter the authors institute
+% addresses. The \institute command is defined here.
+
+\newcounter{@inst}
+\newcounter{@auth}
+\newcounter{auco}
+\newdimen\instindent
+\newbox\authrun
+\newtoks\authorrunning
+\newtoks\tocauthor
+\newbox\titrun
+\newtoks\titlerunning
+\newtoks\toctitle
+
+\def\clearheadinfo{\gdef\@author{No Author Given}%
+ \gdef\@title{No Title Given}%
+ \gdef\@subtitle{}%
+ \gdef\@institute{No Institute Given}%
+ \gdef\@thanks{}%
+ \global\titlerunning={}\global\authorrunning={}%
+ \global\toctitle={}\global\tocauthor={}}
+
+\def\institute#1{\gdef\@institute{#1}}
+
+\def\institutename{\par
+ \begingroup
+ \parskip=\z@
+ \parindent=\z@
+ \setcounter{@inst}{1}%
+ \def\and{\par\stepcounter{@inst}%
+ \noindent$^{\the@inst}$\enspace\ignorespaces}%
+ \setbox0=\vbox{\def\thanks##1{}\@institute}%
+ \ifnum\c@@inst=1\relax
+ \gdef\fnnstart{0}%
+ \else
+ \xdef\fnnstart{\c@@inst}%
+ \setcounter{@inst}{1}%
+ \noindent$^{\the@inst}$\enspace
+ \fi
+ \ignorespaces
+ \@institute\par
+ \endgroup}
+
+\def\@fnsymbol#1{\ensuremath{\ifcase#1\or\star\or{\star\star}\or
+ {\star\star\star}\or \dagger\or \ddagger\or
+ \mathchar "278\or \mathchar "27B\or \|\or **\or \dagger\dagger
+ \or \ddagger\ddagger \else\@ctrerr\fi}}
+
+\def\inst#1{\unskip$^{#1}$}
+\def\orcidID#1{\unskip$^{[#1]}$} % added MR 2018-03-10
+\def\fnmsep{\unskip$^,$}
+\def\email#1{{\tt#1}}
+
+\AtBeginDocument{\@ifundefined{url}{\def\url#1{#1}}{}%
+\@ifpackageloaded{babel}{%
+\@ifundefined{extrasenglish}{}{\addto\extrasenglish{\switcht@albion}}%
+\@ifundefined{extrasfrenchb}{}{\addto\extrasfrenchb{\switcht@francais}}%
+\@ifundefined{extrasgerman}{}{\addto\extrasgerman{\switcht@deutsch}}%
+\@ifundefined{extrasngerman}{}{\addto\extrasngerman{\switcht@deutsch}}%
+}{\switcht@@therlang}%
+\providecommand{\keywords}[1]{\def\and{{\textperiodcentered} }%
+\par\addvspace\baselineskip
+\noindent\keywordname\enspace\ignorespaces#1}%
+\@ifpackageloaded{hyperref}{%
+\def\doi#1{\href{https://doi.org/\detokenize{#1}}{\url{https://doi.org/\detokenize{#1}}}}}{
+\def\doi#1{https://doi.org/\detokenize{#1}}}
+}
+\def\homedir{\~{ }}
+
+\def\subtitle#1{\gdef\@subtitle{#1}}
+\clearheadinfo
+%
+%%% to avoid hyperref warnings
+\providecommand*{\toclevel@author}{999}
+%%% to make title-entry parent of section-entries
+\providecommand*{\toclevel@title}{0}
+%
+\renewcommand\maketitle{\newpage
+\phantomsection
+ \refstepcounter{chapter}%
+ \stepcounter{section}%
+ \setcounter{section}{0}%
+ \setcounter{subsection}{0}%
+ \setcounter{figure}{0}
+ \setcounter{table}{0}
+ \setcounter{equation}{0}
+ \setcounter{footnote}{0}%
+ \begingroup
+ \parindent=\z@
+ \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
+ \if@twocolumn
+ \ifnum \col@number=\@ne
+ \@maketitle
+ \else
+ \twocolumn[\@maketitle]%
+ \fi
+ \else
+ \newpage
+ \global\@topnum\z@ % Prevents figures from going at top of page.
+ \@maketitle
+ \fi
+ \thispagestyle{empty}\@thanks
+%
+ \def\\{\unskip\ \ignorespaces}\def\inst##1{\unskip{}}%
+ \def\thanks##1{\unskip{}}\def\fnmsep{\unskip}%
+ \instindent=\hsize
+ \advance\instindent by-\headlineindent
+ \if!\the\toctitle!\addcontentsline{toc}{title}{\@title}\else
+ \addcontentsline{toc}{title}{\the\toctitle}\fi
+ \if@runhead
+ \if!\the\titlerunning!\else
+ \edef\@title{\the\titlerunning}%
+ \fi
+ \global\setbox\titrun=\hbox{\small\rm\unboldmath\ignorespaces\@title}%
+ \ifdim\wd\titrun>\instindent
+ \typeout{Title too long for running head. Please supply}%
+ \typeout{a shorter form with \string\titlerunning\space prior to
+ \string\maketitle}%
+ \global\setbox\titrun=\hbox{\small\rm
+ Title Suppressed Due to Excessive Length}%
+ \fi
+ \xdef\@title{\copy\titrun}%
+ \fi
+%
+ \if!\the\tocauthor!\relax
+ {\def\and{\noexpand\protect\noexpand\and}%
+ \def\inst##1{}% added MR 2017-09-20 to remove inst numbers from the TOC
+ \def\orcidID##1{}% added MR 2017-09-20 to remove ORCID ids from the TOC
+ \protected@xdef\toc@uthor{\@author}}%
+ \else
+ \def\\{\noexpand\protect\noexpand\newline}%
+ \protected@xdef\scratch{\the\tocauthor}%
+ \protected@xdef\toc@uthor{\scratch}%
+ \fi
+ \addtocontents{toc}{\noexpand\protect\noexpand\authcount{\the\c@auco}}%
+ \addcontentsline{toc}{author}{\toc@uthor}%
+ \if@runhead
+ \if!\the\authorrunning!
+ \value{@inst}=\value{@auth}%
+ \setcounter{@auth}{1}%
+ \else
+ \edef\@author{\the\authorrunning}%
+ \fi
+ \global\setbox\authrun=\hbox{\def\inst##1{}% added MR 2017-09-20 to remove inst numbers from the runninghead
+ \def\orcidID##1{}% added MR 2017-09-20 to remove ORCID ids from the runninghead
+ \small\unboldmath\@author\unskip}%
+ \ifdim\wd\authrun>\instindent
+ \typeout{Names of authors too long for running head. Please supply}%
+ \typeout{a shorter form with \string\authorrunning\space prior to
+ \string\maketitle}%
+ \global\setbox\authrun=\hbox{\small\rm
+ Authors Suppressed Due to Excessive Length}%
+ \fi
+ \xdef\@author{\copy\authrun}%
+ \markboth{\@author}{\@title}%
+ \fi
+ \endgroup
+ \setcounter{footnote}{\fnnstart}%
+ \clearheadinfo}
+%
+\def\@maketitle{\newpage
+ \markboth{}{}%
+ \def\lastand{\ifnum\value{@inst}=2\relax
+ \unskip{} \andname\
+ \else
+ \unskip \lastandname\
+ \fi}%
+ \def\and{\stepcounter{@auth}\relax
+ \ifnum\value{@auth}=\value{@inst}%
+ \lastand
+ \else
+ \unskip,
+ \fi}%
+ \begin{center}%
+ \let\newline\\
+ {\Large \bfseries\boldmath
+ \pretolerance=10000
+ \@title \par}\vskip .8cm
+\if!\@subtitle!\else {\large \bfseries\boldmath
+ \vskip -.65cm
+ \pretolerance=10000
+ \@subtitle \par}\vskip .8cm\fi
+ \setbox0=\vbox{\setcounter{@auth}{1}\def\and{\stepcounter{@auth}}%
+ \def\thanks##1{}\@author}%
+ \global\value{@inst}=\value{@auth}%
+ \global\value{auco}=\value{@auth}%
+ \setcounter{@auth}{1}%
+{\lineskip .5em
+\noindent\ignorespaces
+\@author\vskip.35cm}
+ {\small\institutename}
+ \end{center}%
+ }
+
+% definition of the "\spnewtheorem" command.
+%
+% Usage:
+%
+% \spnewtheorem{env_nam}{caption}[within]{cap_font}{body_font}
+% or \spnewtheorem{env_nam}[numbered_like]{caption}{cap_font}{body_font}
+% or \spnewtheorem*{env_nam}{caption}{cap_font}{body_font}
+%
+% New is "cap_font" and "body_font". It stands for
+% fontdefinition of the caption and the text itself.
+%
+% "\spnewtheorem*" gives a theorem without number.
+%
+% A defined spnewthoerem environment is used as described
+% by Lamport.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\@thmcountersep{}
+\def\@thmcounterend{.}
+
+\def\spnewtheorem{\@ifstar{\@sthm}{\@Sthm}}
+
+% definition of \spnewtheorem with number
+
+\def\@spnthm#1#2{%
+ \@ifnextchar[{\@spxnthm{#1}{#2}}{\@spynthm{#1}{#2}}}
+\def\@Sthm#1{\@ifnextchar[{\@spothm{#1}}{\@spnthm{#1}}}
+
+\def\@spxnthm#1#2[#3]#4#5{\expandafter\@ifdefinable\csname #1\endcsname
+ {\@definecounter{#1}\@addtoreset{#1}{#3}%
+ \expandafter\xdef\csname the#1\endcsname{\expandafter\noexpand
+ \csname the#3\endcsname \noexpand\@thmcountersep \@thmcounter{#1}}%
+ \expandafter\xdef\csname #1name\endcsname{#2}%
+ \global\@namedef{#1}{\@spthm{#1}{\csname #1name\endcsname}{#4}{#5}}%
+ \global\@namedef{end#1}{\@endtheorem}}}
+
+\def\@spynthm#1#2#3#4{\expandafter\@ifdefinable\csname #1\endcsname
+ {\@definecounter{#1}%
+ \expandafter\xdef\csname the#1\endcsname{\@thmcounter{#1}}%
+ \expandafter\xdef\csname #1name\endcsname{#2}%
+ \global\@namedef{#1}{\@spthm{#1}{\csname #1name\endcsname}{#3}{#4}}%
+ \global\@namedef{end#1}{\@endtheorem}}}
+
+\def\@spothm#1[#2]#3#4#5{%
+ \@ifundefined{c@#2}{\@latexerr{No theorem environment `#2' defined}\@eha}%
+ {\expandafter\@ifdefinable\csname #1\endcsname
+ {\newaliascnt{#1}{#2}%
+ \expandafter\xdef\csname #1name\endcsname{#3}%
+ \global\@namedef{#1}{\@spthm{#1}{\csname #1name\endcsname}{#4}{#5}}%
+ \global\@namedef{end#1}{\@endtheorem}}}}
+
+\def\@spthm#1#2#3#4{\topsep 7\p@ \@plus2\p@ \@minus4\p@
+\refstepcounter{#1}%
+\@ifnextchar[{\@spythm{#1}{#2}{#3}{#4}}{\@spxthm{#1}{#2}{#3}{#4}}}
+
+\def\@spxthm#1#2#3#4{\@spbegintheorem{#2}{\csname the#1\endcsname}{#3}{#4}%
+ \ignorespaces}
+
+\def\@spythm#1#2#3#4[#5]{\@spopargbegintheorem{#2}{\csname
+ the#1\endcsname}{#5}{#3}{#4}\ignorespaces}
+
+\def\@spbegintheorem#1#2#3#4{\trivlist
+ \item[\hskip\labelsep{#3#1\ #2\@thmcounterend}]#4}
+
+\def\@spopargbegintheorem#1#2#3#4#5{\trivlist
+ \item[\hskip\labelsep{#4#1\ #2}]{#4(#3)\@thmcounterend\ }#5}
+
+% definition of \spnewtheorem* without number
+
+\def\@sthm#1#2{\@Ynthm{#1}{#2}}
+
+\def\@Ynthm#1#2#3#4{\expandafter\@ifdefinable\csname #1\endcsname
+ {\global\@namedef{#1}{\@Thm{\csname #1name\endcsname}{#3}{#4}}%
+ \expandafter\xdef\csname #1name\endcsname{#2}%
+ \global\@namedef{end#1}{\@endtheorem}}}
+
+\def\@Thm#1#2#3{\topsep 7\p@ \@plus2\p@ \@minus4\p@
+\@ifnextchar[{\@Ythm{#1}{#2}{#3}}{\@Xthm{#1}{#2}{#3}}}
+
+\def\@Xthm#1#2#3{\@Begintheorem{#1}{#2}{#3}\ignorespaces}
+
+\def\@Ythm#1#2#3[#4]{\@Opargbegintheorem{#1}
+ {#4}{#2}{#3}\ignorespaces}
+
+\def\@Begintheorem#1#2#3{#3\trivlist
+ \item[\hskip\labelsep{#2#1\@thmcounterend}]}
+
+\def\@Opargbegintheorem#1#2#3#4{#4\trivlist
+ \item[\hskip\labelsep{#3#1}]{#3(#2)\@thmcounterend\ }}
+
+\if@envcntsect
+ \def\@thmcountersep{.}
+ \spnewtheorem{theorem}{Theorem}[section]{\bfseries}{\itshape}
+\else
+ \spnewtheorem{theorem}{Theorem}{\bfseries}{\itshape}
+ \if@envcntreset
+ \@addtoreset{theorem}{section}
+ \else
+ \@addtoreset{theorem}{chapter}
+ \fi
+\fi
+
+%definition of divers theorem environments
+\spnewtheorem*{claim}{Claim}{\itshape}{\rmfamily}
+\spnewtheorem*{proof}{Proof}{\itshape}{\rmfamily}
+\if@envcntsame % alle Umgebungen wie Theorem.
+ \def\spn@wtheorem#1#2#3#4{\@spothm{#1}[theorem]{#2}{#3}{#4}}
+\else % alle Umgebungen mit eigenem Zaehler
+ \if@envcntsect % mit section numeriert
+ \def\spn@wtheorem#1#2#3#4{\@spxnthm{#1}{#2}[section]{#3}{#4}}
+ \else % nicht mit section numeriert
+ \if@envcntreset
+ \def\spn@wtheorem#1#2#3#4{\@spynthm{#1}{#2}{#3}{#4}
+ \@addtoreset{#1}{section}}
+ \else
+ \def\spn@wtheorem#1#2#3#4{\@spynthm{#1}{#2}{#3}{#4}
+ \@addtoreset{#1}{chapter}}%
+ \fi
+ \fi
+\fi
+\spn@wtheorem{case}{Case}{\itshape}{\rmfamily}
+\spn@wtheorem{conjecture}{Conjecture}{\itshape}{\rmfamily}
+\spn@wtheorem{corollary}{Corollary}{\bfseries}{\itshape}
+\spn@wtheorem{definition}{Definition}{\bfseries}{\itshape}
+\spn@wtheorem{example}{Example}{\itshape}{\rmfamily}
+\spn@wtheorem{exercise}{Exercise}{\itshape}{\rmfamily}
+\spn@wtheorem{lemma}{Lemma}{\bfseries}{\itshape}
+\spn@wtheorem{note}{Note}{\itshape}{\rmfamily}
+\spn@wtheorem{problem}{Problem}{\itshape}{\rmfamily}
+\spn@wtheorem{property}{Property}{\itshape}{\rmfamily}
+\spn@wtheorem{proposition}{Proposition}{\bfseries}{\itshape}
+\spn@wtheorem{question}{Question}{\itshape}{\rmfamily}
+\spn@wtheorem{solution}{Solution}{\itshape}{\rmfamily}
+\spn@wtheorem{remark}{Remark}{\itshape}{\rmfamily}
+
+\def\@takefromreset#1#2{%
+ \def\@tempa{#1}%
+ \let\@tempd\@elt
+ \def\@elt##1{%
+ \def\@tempb{##1}%
+ \ifx\@tempa\@tempb\else
+ \@addtoreset{##1}{#2}%
+ \fi}%
+ \expandafter\expandafter\let\expandafter\@tempc\csname cl@#2\endcsname
+ \expandafter\def\csname cl@#2\endcsname{}%
+ \@tempc
+ \let\@elt\@tempd}
+
+\def\theopargself{\def\@spopargbegintheorem##1##2##3##4##5{\trivlist
+ \item[\hskip\labelsep{##4##1\ ##2}]{##4##3\@thmcounterend\ }##5}
+ \def\@Opargbegintheorem##1##2##3##4{##4\trivlist
+ \item[\hskip\labelsep{##3##1}]{##3##2\@thmcounterend\ }}
+ }
+
+\renewenvironment{abstract}{%
+ \list{}{\advance\topsep by0.35cm\relax\small
+ \leftmargin=1cm
+ \labelwidth=\z@
+ \listparindent=\z@
+ \itemindent\listparindent
+ \rightmargin\leftmargin}\item[\hskip\labelsep
+ \bfseries\abstractname]}
+ {\endlist}
+
+\newdimen\headlineindent % dimension for space between
+\headlineindent=1.166cm % number and text of headings.
+
+\def\ps@headings{\let\@mkboth\@gobbletwo
+ \let\@oddfoot\@empty\let\@evenfoot\@empty
+ \def\@evenhead{\normalfont\small\rlap{\thepage}\hspace{\headlineindent}%
+ \leftmark\hfil}
+ \def\@oddhead{\normalfont\small\hfil\rightmark\hspace{\headlineindent}%
+ \llap{\thepage}}
+ \def\chaptermark##1{}%
+ \def\sectionmark##1{}%
+ \def\subsectionmark##1{}}
+
+\def\ps@titlepage{\let\@mkboth\@gobbletwo
+ \let\@oddfoot\@empty\let\@evenfoot\@empty
+ \def\@evenhead{\normalfont\small\rlap{\thepage}\hspace{\headlineindent}%
+ \hfil}
+ \def\@oddhead{\normalfont\small\hfil\hspace{\headlineindent}%
+ \llap{\thepage}}
+ \def\chaptermark##1{}%
+ \def\sectionmark##1{}%
+ \def\subsectionmark##1{}}
+
+\if@runhead\ps@headings\else
+\ps@empty\fi
+
+\setlength\arraycolsep{1.4\p@}
+\setlength\tabcolsep{1.4\p@}
+
+\endinput
+%end of file llncs.cls
diff --git a/macros/latex/contrib/llncs/llncsdoc.pdf b/macros/latex/contrib/llncs/llncsdoc.pdf
new file mode 100644
index 0000000000..f0983cf795
--- /dev/null
+++ b/macros/latex/contrib/llncs/llncsdoc.pdf
Binary files differ
diff --git a/macros/latex/contrib/llncs/llncsdoc.tex b/macros/latex/contrib/llncs/llncsdoc.tex
new file mode 100644
index 0000000000..b8c8f38540
--- /dev/null
+++ b/macros/latex/contrib/llncs/llncsdoc.tex
@@ -0,0 +1,422 @@
+% This is LLNCSDOC.TEX the documentation file of
+% the LaTeX2e class from Springer-Verlag
+% for Lecture Notes in Computer Science, version 2.21
+\documentclass{llncs}
+\usepackage{llncsdoc}
+\usepackage{graphicx}
+\usepackage{doc}
+\usepackage[dvips,bookmarksopen]{hyperref}
+%
+\makeatletter\@twosidefalse\@mparswitchfalse\makeatother
+\begin{document}
+\title{Instructions for Using Springer's \texttt{llncs} Class for
+Computer Science Proceedings Papers}
+%
+\subtitle{\texttt{llncs}, Version 2.21, Jan 12, 2022}
+%
+\author{}
+\institute{}
+
+\maketitle \thispagestyle{empty}
+%
+\section{Installation}
+%
+Copy \texttt{llncs.cls} to a directory that is searched by \LaTeX{},
+e.g. either your \texttt{texmf} tree or the local work directory with your main
+{\LaTeX} file.
+
+%
+\section{Working with the \texttt{llncs} Document Class}
+%
+\subsection{General Information}
+The \texttt{llncs} class is an extension of the standard \LaTeX{} \texttt{article}
+class. Therefore you may use all \texttt{article} commands in your
+manuscript.
+
+If you are already familiar with \LaTeX{}, the \texttt{llncs} class should
+not give you any major difficulties. It basically adjusts the layout
+to the required standard, defining styles and spacing of headings
+and captions and setting the printing area to 122\,mm horizontally
+by 193\,mm vertically. To keep the layout consistent, we kindly ask
+you to refrain from using any \LaTeX{} or \TeX{} command that
+modifies these settings (i.e. \verb|\textheight|, \verb|\vspace|,
+\verb|baselinestretch|, etc.). Such manual layout adjustments should
+be limited to very exceptional cases.
+
+In addition to defining the general layout, the \texttt{llncs} document class
+provides some special commands for typesetting the contribution
+header, i.e. title, authors, affiliations, abstract, and additional
+metadata. These special commands are described in Sect.~\ref{Sec2}.
+
+For a more detailed description of how to prepare your text,
+illustrations, and references, see the {\em Springer Guidelines for
+Authors of Proceedings}.
+
+
+\subsection{How to Use the \texttt{llncs} Document Class}
+The \texttt{llncs} class is invoked by replacing \texttt{article} by \texttt{llncs} in
+the first line of your \LaTeX{} document:
+\begin{verbatim}
+\documentclass{llncs}
+%
+\begin{document}
+ <Your contribution>
+\end{document}
+\end{verbatim}
+%
+If your file is already coded with \LaTeX{}, you can easily adapt it
+to the \texttt{llncs} document class by replacing
+\begin{verbatim}
+\documentclass{article}
+\end{verbatim}
+with
+\begin{verbatim}
+\documentclass{llncs}
+\end{verbatim}
+
+
+\section{How to Code the Header of Your Paper}\label{Sec2}
+\label{contbegin}
+\subsection{Title}
+%
+\DescribeMacro{\title} Please code the title of your contribution as
+follows:
+\begin{verbatim}
+\title{<Your contribution title>}
+\end{verbatim}
+All words in titles should be capitalized except for conjunctions,
+prepositions (e.g.\ on, of, by, and, or, but, from, with, without,
+under), and definite/indefinite articles (the, a, an), unless they
+appear at the beginning. Formula letters are typeset as in the text.
+Long titles that run over multiple lines can be wrapped explicitly
+with \verb|\\|. Titles have no end punctuation.
+
+Acknowledgements should generally be placed in an unnumbered
+subsection at the end of the paper. If you still need to refer to a
+support or funding program in a note to the title, you can use
+the\DescribeMacro{\thanks} \verb|\thanks| macro inside the title:
+\begin{verbatim}
+\title{<Your contribution title>\thanks{<granted by x>}}
+\end{verbatim}
+Please do not use \verb|\thanks| inside \verb|\author| or
+\verb|\institute| as footnotes for these elements are not supported
+in the online version and will therefore be dropped.
+
+\DescribeMacro{\fnmsep} If you need two or more footnotes please
+separate them with \verb|\fnmsep| (i.e. {\itshape f}oot\emph note
+\emph mark \emph{sep}arator).
+
+\DescribeMacro{\titlerunning} If a long title does not fit in the
+single line of the running head, a warning is generated. You can
+specify an abbreviated title for the running head with the command
+\begin{verbatim}
+\titlerunning{<Your abbreviated contribution title>}
+\end{verbatim}
+\DescribeMacro{\subtitle} An optional subtitle may also be added:
+\begin{verbatim}
+\subtitle{<subtitle of your contribution>}
+\end{verbatim}
+
+\subsection{Author(s)}
+\DescribeMacro{\author} The name(s) of the author(s) are specified
+by:
+\begin{verbatim}
+\author{<author(s) name(s)>}
+\end{verbatim}
+\DescribeMacro{\and} If there is more than one author, please
+separate them by \verb|\and|. This makes sure that correct
+punctuation is inserted according to the number of authors.
+
+\DescribeMacro{\inst} Numbers referring to different addresses or
+affiliations should be attached to each author with the
+\verb|\inst{<number>}| command. If an author is affiliated with
+multiple institutions the numbers should be separated by a comma,
+for example \verb|\inst{2,3}|.
+
+\DescribeMacro{\orcidID} ORCID identifiers can be included with
+\begin{verbatim}
+\orcidID{<ORCID identifier>}
+\end{verbatim}
+The ORCID (Open Researcher and Contributor ID) registry provides
+authors with unique digital identifiers that distinguish them from
+other researchers and help them link their research activities to
+these identifiers. Authors who are not yet registered with ORCID are
+encouraged to apply for an individual ORCID id at
+\url{https://www.orcid.org} and to include it in their papers. In
+the final publication, the ORCID id will be replaced by an ORCID
+icon, which will link from the eBook to the
+actual ID in the ORCID database. The ORCID icon will also replace
+the number in the printed book.
+
+If you have done this correctly, the author line now reads, for
+example:
+\begin{verbatim}
+\author{First Author\inst{1}\orcidID{0000-1111-2222-3333} \and
+Second Author\inst{2,3}\orcidID{1111-2222-3333-4444}}
+\end{verbatim}
+The given name(s) should always be followed by the family name(s).
+Authors who have more than one family name should indicate which
+part of their name represents the family name(s), for example by
+non-breaking spaces \verb|Jos\'{e} Martinez~Perez| or curly braces
+\verb|Jos\'{e} {Martinez Perez}|.
+
+\DescribeMacro{\authorrunning} As given name(s) are to be shortened
+to initials in the running heads, specifying an abbreviated author
+list with the optional command:
+\begin{verbatim}
+\authorrunning{<abbreviated author list>}
+\end{verbatim}
+might add some clarity about the correct representation of author
+names, in the running-heads as well as in the author index.
+
+\subsection{Affiliations}
+\DescribeMacro{\institute} Addresses of institutes, companies, etc.
+should be given in \verb|\institute|.
+
+\DescribeMacro{\and} Multiple affiliations are separated by
+\verb|\and|, which automatically assures correct numbering:
+\begin{verbatim}
+\institute{<name of an institute>
+\and <name of the next institute>
+\and <name of the next institute>}
+\end{verbatim}
+\DescribeMacro{\email}Inside \verb|\institute| you can use
+\begin{verbatim}
+\email{<email address>}
+\end{verbatim}
+\DescribeMacro{\url}and
+\begin{verbatim}
+\url{<url>}
+\end{verbatim}
+to provide author email addresses and Web pages. If you need to
+typeset the tilde character -- e.g. for your Web page in your unix
+system's home directory -- the \verb|\homedir| command will do this.
+If multiple authors have the same affiliation, please check that the
+order of email addresses matches the sequence of (affiliated) author
+names.
+
+Please note that, if email addresses are given in your paper, they
+will also be included in the metadata of the online version.
+
+\subsection{Format the Header}
+\DescribeMacro{\maketitle} The command \verb|\maketitle| formats the
+header of your paper. If you leave it out the work done so far will
+produce \emph{no} text.
+
+\subsection{Abstract and Keywords}
+\DescribeEnv{abstract}The abstract is coded as follows:
+\begin{verbatim}
+\begin{abstract}
+<Text of the summary of your paper>
+\end{abstract}
+\end{verbatim}
+\DescribeMacro{\keywords} Keywords should be specified inside the
+\verb|abstract| environment. \DescribeMacro{\and}Please capitalize
+the first letter of each keyword and again separate them with
+\verb|\and|:
+\begin{verbatim}
+\keywords{First keyword \and Second keyword \and Third keyword}
+\end{verbatim}
+The keyword separator will then be properly rendered as a middle
+dot.
+
+\section{How to Code the Body of Your Paper}
+%
+\subsection{General Rules}
+From a technical point of view, the \texttt{llncs} document class does not
+require any specific {\LaTeX} coding in the body of your paper. You
+can simply use the commands provided by the `article' document
+class. For more information about what will be done with your
+manuscript before publication, please refer to the {\em Springer
+Guidelines for Authors of Proceedings}.
+
+\subsection{Special Math Characters}
+The \texttt{llncs} document class supports some additional special
+characters:\smallskip
+\begin{center}
+\begin{tabular}{l@{\hspace{1em}yields\hspace{1em}}
+c@{\hspace{3em}}l@{\hspace{1em}yields\hspace{1em}}c}
+\verb|\grole| & $\grole$ & \verb|\getsto| & $\getsto$\\
+\verb|\lid| & $\lid$ & \verb|\gid| & $\gid$
+\end{tabular}\smallskip
+\end{center}
+If you need blackboard bold characters, i.e. for sets of numbers,
+please load the related \AmSTeX fonts. If for some reason this is
+not possible you can also use the following commands from the \texttt{llncs}
+class:\smallskip
+\begin{center}
+\begin{tabular}{l@{\hspace{1em}yields\hspace{1em}}
+c@{\hspace{3em}}l@{\hspace{1em}yields\hspace{1em}}c}
+\verb|\bbbc| & $\bbbc$ & \verb|\bbbf| & $\bbbf$\\
+\verb|\bbbh| & $\bbbh$ & \verb|\bbbk| & $\bbbk$\\
+\verb|\bbbm| & $\bbbm$ & \verb|\bbbn| & $\bbbn$\\
+\verb|\bbbp| & $\bbbp$ & \verb|\bbbq| & $\bbbq$\\
+\verb|\bbbr| & $\bbbr$ & \verb|\bbbs| & $\bbbs$\\
+\verb|\bbbt| & $\bbbt$ & \verb|\bbbz| & $\bbbz$\\
+\verb|\bbbone| & $\bbbone$
+\end{tabular}\smallskip
+\end{center}
+Please note that all these characters are only available in math
+mode.
+
+\section{Theorems, Definitions, and Proofs}\label{builtintheo}
+\subsection{Predefined Theorem-Like Environments}
+\DescribeEnv{corollary}\DescribeEnv{definition}\DescribeEnv{lemma}\DescribeEnv{proposition}\DescribeEnv{theorem}%
+Several theorem-like environments are predefined in the \texttt{llncs}
+document class. The following environments have a bold run-in
+heading, while the following text is in italics:
+\begin{verbatim}
+\begin{corollary} <text> \end{corollary}
+\begin{definition} <text> \end{definition}
+\begin{lemma} <text> \end{lemma}
+\begin{proposition} <text> \end{proposition}
+\begin{theorem} <text> \end{theorem}
+\end{verbatim}
+\DescribeEnv{case}\DescribeEnv{conjecture}\DescribeEnv{example}\DescribeEnv{exercise}\DescribeEnv{note}%
+\DescribeEnv{problem}\DescribeEnv{property}\DescribeEnv{question}\DescribeEnv{remark}\DescribeEnv{solution}%
+Other theorem-like environments render the text in roman, while the
+run-in heading is bold as well:
+\begin{verbatim}
+\begin{case} <text> \end{case}
+\begin{conjecture} <text> \end{conjecture}
+\begin{example} <text> \end{example}
+\begin{exercise} <text> \end{exercise}
+\begin{note} <text> \end{note}
+\begin{problem} <text> \end{problem}
+\begin{property} <text> \end{property}
+\begin{question} <text> \end{question}
+\begin{remark} <text> \end{remark}
+\begin{solution} <text> \end{solution}
+\end{verbatim}
+\DescribeEnv{claim}\DescribeEnv{proof} Finally, there are also two
+unnumbered environments that have the run-in heading in italics and
+the text in upright roman.
+\begin{verbatim}
+\begin{claim} <text> \end{claim}
+\begin{proof} <text> \end{proof}
+\end{verbatim}
+\DescribeMacro{\qed}Proofs may contain an eye catching square, which
+can be inserted with \verb|\qed|) before the environment ends.
+
+\subsection{User-Defined Theorem-Like Environments}
+\DescribeMacro{\spnewtheorem}We have enhanced the standard
+\verb|\newtheorem| command and slightly changed its syntax to get
+two new commands \verb|\spnewtheorem| and \verb|\spnewtheorem*| that
+now can be used to define additional environments. They require two
+additional arguments, namely the font style of the label and the
+font style of the text of the new environment:
+\begin{verbatim}
+\spnewtheorem{<env_nam>}[<num_like>]{<caption>}{<cap_font>}{<body_font>}
+\end{verbatim}
+For example,
+\begin{verbatim}
+\spnewtheorem{maintheorem}[theorem]{Main Theorem}{\bfseries}{\itshape}
+\end{verbatim}
+will create a {\em main theorem\/} environment that is numbered
+together with the predefined {\em theorem\/}. The sharing of the
+default counter (\verb|[theorem]|) is desired. If you omit the
+optional second argument of \verb|\spnewtheorem|, a separate counter
+for your new environment is used throughout your document.
+
+In combination with the (obsolete) class option \verb|envcountsect|
+(see. Sect.~\ref{SecClassOptions}), the \verb|\spnewtheorem| command
+also supports the syntax:
+\begin{verbatim}
+\spnewtheorem{<env_nam>}{<caption>}[<within>]{<cap_font>}{<body_font>}
+\end{verbatim}
+With the parameter \verb|<within>|, you can control the sectioning
+element that resets the theorem counters. If you specify, for
+example, \verb|subsection|, the newly defined environment is
+numbered subsectionwise.
+
+\DescribeMacro{\spnewtheorem*}If you wish to add an unnumbered
+environment, please use the syntax
+\begin{verbatim}
+\spnewtheorem*{<env_nam>}{<caption>}{<cap_font>}{<body_font>}
+\end{verbatim}
+
+
+
+%
+\section{References}
+\label{refer}
+%
+There are three options for citing references:
+\begin{itemize}
+\item arabic numbers, i.e. [1], [3--5], [4--6,9],
+\item labels, i.e. [CE1], [AB1,XY2],
+\item author/year system, (Smith et al. 2000), (Miller 1999a, 12; Brown
+2018).
+\end{itemize}
+We prefer citations with arabic numbers, i.e. the usage of
+\verb|\bibitem| without an optional parameter.
+\DescribeMacro{citeauthoryear}If you want to use the author/year
+system, you can use the class option \verb|citeauthoryear|, i.e.
+\begin{verbatim}
+\documentclass[citeauthoryear]{llncs}
+\end{verbatim}
+Please note that this option does not automatically change your
+citations to the author/year style. It basically redefines the
+\verb|\bibitem| command to take the publication year as an optional
+parameter that is displayed instead of an arabic number. Author
+name(s) and, if necessary, parentheses are to be typed manually. If
+your reference reads
+\begin{verbatim}
+\bibitem[2016]{vdaalst:2016}
+van der Aalst, W.: Process Mining, 2nd ed. Springer, Heidelberg (2016)
+\end{verbatim}
+and is cited as follows:
+\begin{verbatim}
+... is shown by van der Aalst (\cite{vdaalst:2016})
+\end{verbatim}
+the resulting text will be:\begin{quote} ``\dots is shown by van der
+Aalst (2016).''
+\end{quote}
+
+\DescribeMacro{splncs04.bst}We encourage you to use {\sc Bib}\TeX{}
+for typesetting your references. For formatting the bibliography
+according to Springer's standard (for mathematics, physical
+sciences, and computer science), please use the bibliography style
+file \verb|splncs04.bst| that comes with the \texttt{llncs} document class.
+You simply need to add \verb|\bibliographystyle{splncs04}| to your
+document. DOIs should be provided in the doi field of your .bib
+database. {\sc Bib}\TeX{} will then automatically add them to your
+references. Please note that we do not provide an option to
+implement
+
+\DescribeMacro{\doi}If you do not use {\sc Bib}\TeX{}, you can
+include a DOI with the \verb|\doi| command:
+\begin{verbatim}
+\doi{<DOI>}
+\end{verbatim}
+The DOI will be expanded to the URL \verb|https://doi.org/<DOI>| in
+accordance with the CrossRef guidelines.
+
+\section{Obsolete Class Options}\label{SecClassOptions}
+The \texttt{llncs} document class contains several class options that have
+become obsolete over the years. We only mention them for
+completeness:
+\begin{itemize}
+\item \DescribeMacro{orivec}The \texttt{llncs} document class changes the formatting of
+vectors coded with \verb|\vec| to boldface italics. If you
+absolutely need the original {\LaTeX} design for vectors, i.e. an
+arrow above the related variable, you can restore it with the
+\verb|orivec| option.
+\item \DescribeMacro{envcountsame}All theorem-like environments
+share one counter, i.e. Theorem 1, Lemma 2, Corollary 3, etc.
+\item \DescribeMacro{envcountreset}All theorem-like environments
+are numbered per section, i.e. the related counters are reset to 1
+in every section.
+\item \DescribeMacro{envcountsect}All theorem-like environments
+are numbered per section, and the section number added to the
+individual counter, i.e. Theorem 1.2, Lemma 2.2, etc.
+\item \DescribeMacro{openbib}This option produces the ``open'' bibliography style, in which each block starts
+on a new line, and succeeding lines in a block are indented by
+\verb|\bibindent|.
+\item \DescribeMacro{oribibl}This option restores the original
+{\LaTeX} definitions for the bibliography and the \verb|\cite|
+mechanism that some {\sc Bib}\TeX{} applications rely on.
+\end{itemize}
+%
+%
+\end{document}
diff --git a/macros/latex/contrib/llncs/splncs04.bst b/macros/latex/contrib/llncs/splncs04.bst
new file mode 100644
index 0000000000..3be8de3ac7
--- /dev/null
+++ b/macros/latex/contrib/llncs/splncs04.bst
@@ -0,0 +1,1548 @@
+%% BibTeX bibliography style `splncs03'
+%%
+%% BibTeX bibliography style for use with numbered references in
+%% Springer Verlag's "Lecture Notes in Computer Science" series.
+%% (See Springer's documentation for llncs.cls for
+%% more details of the suggested reference format.) Note that this
+%% file will not work for author-year style citations.
+%%
+%% Use \documentclass{llncs} and \bibliographystyle{splncs03}, and cite
+%% a reference with (e.g.) \cite{smith77} to get a "[1]" in the text.
+%%
+%% This file comes to you courtesy of Maurizio "Titto" Patrignani of
+%% Dipartimento di Informatica e Automazione Universita' Roma Tre
+%%
+%% ================================================================================================
+%% This was file `titto-lncs-02.bst' produced on Wed Apr 1, 2009
+%% Edited by hand by titto based on `titto-lncs-01.bst' (see below)
+%%
+%% CHANGES (with respect to titto-lncs-01.bst):
+%% - Removed the call to \urlprefix (thus no "URL" string is added to the output)
+%% ================================================================================================
+%% This was file `titto-lncs-01.bst' produced on Fri Aug 22, 2008
+%% Edited by hand by titto based on `titto.bst' (see below)
+%%
+%% CHANGES (with respect to titto.bst):
+%% - Removed the "capitalize" command for editors string "(eds.)" and "(ed.)"
+%% - Introduced the functions titto.bbl.pages and titto.bbl.page for journal pages (without "pp.")
+%% - Added a new.sentence command to separate with a dot booktitle and series in the inproceedings
+%% - Commented all new.block commands before urls and notes (to separate them with a comma)
+%% - Introduced the functions titto.bbl.volume for handling journal volumes (without "vol." label)
+%% - Used for editors the same name conventions used for authors (see function format.in.ed.booktitle)
+%% - Removed a \newblock to avoid long spaces between title and "In: ..."
+%% - Added function titto.space.prefix to add a space instead of "~" after the (removed) "vol." label
+%% - Added doi
+%% ================================================================================================
+%% This was file `titto.bst',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% merlin.mbs (with options: `vonx,nm-rvvc,yr-par,jttl-rm,volp-com,jwdpg,jwdvol,numser,ser-vol,jnm-x,btit-rm,bt-rm,edparxc,bkedcap,au-col,in-col,fin-bare,pp,ed,abr,mth-bare,xedn,jabr,and-com,and-com-ed,xand,url,url-blk,em-x,nfss,')
+%% ----------------------------------------
+%% *** Tentative .bst file for Springer LNCS ***
+%%
+%% Copyright 1994-2007 Patrick W Daly
+ % ===============================================================
+ % IMPORTANT NOTICE:
+ % This bibliographic style (bst) file has been generated from one or
+ % more master bibliographic style (mbs) files, listed above.
+ %
+ % This generated file can be redistributed and/or modified under the terms
+ % of the LaTeX Project Public License Distributed from CTAN
+ % archives in directory macros/latex/base/lppl.txt; either
+ % version 1 of the License, or any later version.
+ % ===============================================================
+ % Name and version information of the main mbs file:
+ % \ProvidesFile{merlin.mbs}[2007/04/24 4.20 (PWD, AO, DPC)]
+ % For use with BibTeX version 0.99a or later
+ %-------------------------------------------------------------------
+ % This bibliography style file is intended for texts in ENGLISH
+ % This is a numerical citation style, and as such is standard LaTeX.
+ % It requires no extra package to interface to the main text.
+ % The form of the \bibitem entries is
+ % \bibitem{key}...
+ % Usage of \cite is as follows:
+ % \cite{key} ==>> [#]
+ % \cite[chap. 2]{key} ==>> [#, chap. 2]
+ % where # is a number determined by the ordering in the reference list.
+ % The order in the reference list is alphabetical by authors.
+ %---------------------------------------------------------------------
+
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ doi
+ edition
+ editor
+ eid
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ url
+ volume
+ year
+ }
+ {}
+ { label }
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+STRINGS { s t}
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state mid.sentence =
+ { ", " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+% newline$
+% "\newblock " write$ % removed for titto-lncs-01
+ " " write$ % to avoid long spaces between title and "In: ..."
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull
+ if$
+}
+FUNCTION {fin.entry}
+{ duplicate$ empty$
+ 'pop$
+ 'write$
+ if$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+FUNCTION {add.blank}
+{ " " * before.all 'output.state :=
+}
+
+
+FUNCTION {add.colon}
+{ duplicate$ empty$
+ 'skip$
+ { ":" * add.blank }
+ if$
+}
+
+FUNCTION {date.block}
+{
+ new.block
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+STRINGS {z}
+FUNCTION {remove.dots}
+{ 'z :=
+ ""
+ { z empty$ not }
+ { z #1 #1 substring$
+ z #2 global.max$ substring$ 'z :=
+ duplicate$ "." = 'pop$
+ { * }
+ if$
+ }
+ while$
+}
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+FUNCTION {emphasize}
+{ skip$ }
+
+FUNCTION {embolden}
+{ duplicate$ empty$
+{ pop$ "" }
+{ "\textbf{" swap$ * "}" * }
+if$
+}
+FUNCTION {tie.or.space.prefix}
+{ duplicate$ text.length$ #5 <
+ { "~" }
+ { " " }
+ if$
+ swap$
+}
+FUNCTION {titto.space.prefix} % always introduce a space
+{ duplicate$ text.length$ #3 <
+ { " " }
+ { " " }
+ if$
+ swap$
+}
+
+
+FUNCTION {capitalize}
+{ "u" change.case$ "t" change.case$ }
+
+FUNCTION {space.word}
+{ " " swap$ * " " * }
+ % Here are the language-specific definitions for explicit words.
+ % Each function has a name bbl.xxx where xxx is the English word.
+ % The language selected here is ENGLISH
+FUNCTION {bbl.and}
+{ "and"}
+
+FUNCTION {bbl.etal}
+{ "et~al." }
+
+FUNCTION {bbl.editors}
+{ "eds." }
+
+FUNCTION {bbl.editor}
+{ "ed." }
+
+FUNCTION {bbl.edby}
+{ "edited by" }
+
+FUNCTION {bbl.edition}
+{ "edn." }
+
+FUNCTION {bbl.volume}
+{ "vol." }
+
+FUNCTION {titto.bbl.volume} % for handling journals
+{ "" }
+
+FUNCTION {bbl.of}
+{ "of" }
+
+FUNCTION {bbl.number}
+{ "no." }
+
+FUNCTION {bbl.nr}
+{ "no." }
+
+FUNCTION {bbl.in}
+{ "in" }
+
+FUNCTION {bbl.pages}
+{ "pp." }
+
+FUNCTION {bbl.page}
+{ "p." }
+
+FUNCTION {titto.bbl.pages} % for journals
+{ "" }
+
+FUNCTION {titto.bbl.page} % for journals
+{ "" }
+
+FUNCTION {bbl.chapter}
+{ "chap." }
+
+FUNCTION {bbl.techrep}
+{ "Tech. Rep." }
+
+FUNCTION {bbl.mthesis}
+{ "Master's thesis" }
+
+FUNCTION {bbl.phdthesis}
+{ "Ph.D. thesis" }
+
+MACRO {jan} {"Jan."}
+
+MACRO {feb} {"Feb."}
+
+MACRO {mar} {"Mar."}
+
+MACRO {apr} {"Apr."}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"Jun."}
+
+MACRO {jul} {"Jul."}
+
+MACRO {aug} {"Aug."}
+
+MACRO {sep} {"Sep."}
+
+MACRO {oct} {"Oct."}
+
+MACRO {nov} {"Nov."}
+
+MACRO {dec} {"Dec."}
+
+MACRO {acmcs} {"ACM Comput. Surv."}
+
+MACRO {acta} {"Acta Inf."}
+
+MACRO {cacm} {"Commun. ACM"}
+
+MACRO {ibmjrd} {"IBM J. Res. Dev."}
+
+MACRO {ibmsj} {"IBM Syst.~J."}
+
+MACRO {ieeese} {"IEEE Trans. Software Eng."}
+
+MACRO {ieeetc} {"IEEE Trans. Comput."}
+
+MACRO {ieeetcad}
+ {"IEEE Trans. Comput. Aid. Des."}
+
+MACRO {ipl} {"Inf. Process. Lett."}
+
+MACRO {jacm} {"J.~ACM"}
+
+MACRO {jcss} {"J.~Comput. Syst. Sci."}
+
+MACRO {scp} {"Sci. Comput. Program."}
+
+MACRO {sicomp} {"SIAM J. Comput."}
+
+MACRO {tocs} {"ACM Trans. Comput. Syst."}
+
+MACRO {tods} {"ACM Trans. Database Syst."}
+
+MACRO {tog} {"ACM Trans. Graphic."}
+
+MACRO {toms} {"ACM Trans. Math. Software"}
+
+MACRO {toois} {"ACM Trans. Office Inf. Syst."}
+
+MACRO {toplas} {"ACM Trans. Progr. Lang. Syst."}
+
+MACRO {tcs} {"Theor. Comput. Sci."}
+
+FUNCTION {bibinfo.check}
+{ swap$
+ duplicate$ missing$
+ {
+ pop$ pop$
+ ""
+ }
+ { duplicate$ empty$
+ {
+ swap$ pop$
+ }
+ { swap$
+ pop$
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {bibinfo.warn}
+{ swap$
+ duplicate$ missing$
+ {
+ swap$ "missing " swap$ * " in " * cite$ * warning$ pop$
+ ""
+ }
+ { duplicate$ empty$
+ {
+ swap$ "empty " swap$ * " in " * cite$ * warning$
+ }
+ { swap$
+ pop$
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {format.url}
+{ url empty$
+ { "" }
+% { "\urlprefix\url{" url * "}" * }
+ { "\url{" url * "}" * } % changed in titto-lncs-02.bst
+ if$
+}
+
+FUNCTION {format.doi} % added in splncs04.bst
+{ doi empty$
+ { "" }
+ { after.block 'output.state :=
+ "\doi{" doi * "}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+
+
+STRINGS { bibinfo}
+
+FUNCTION {format.names}
+{ 'bibinfo :=
+ duplicate$ empty$ 'skip$ {
+ 's :=
+ "" 't :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr
+ "{vv~}{ll}{, jj}{, f{.}.}"
+ format.name$
+ bibinfo bibinfo.check
+ 't :=
+ nameptr #1 >
+ {
+ namesleft #1 >
+ { ", " * t * }
+ {
+ s nameptr "{ll}" format.name$ duplicate$ "others" =
+ { 't := }
+ { pop$ }
+ if$
+ "," *
+ t "others" =
+ {
+ " " * bbl.etal *
+ }
+ { " " * t * }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ } if$
+}
+FUNCTION {format.names.ed}
+{
+ 'bibinfo :=
+ duplicate$ empty$ 'skip$ {
+ 's :=
+ "" 't :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr
+ "{f{.}.~}{vv~}{ll}{ jj}"
+ format.name$
+ bibinfo bibinfo.check
+ 't :=
+ nameptr #1 >
+ {
+ namesleft #1 >
+ { ", " * t * }
+ {
+ s nameptr "{ll}" format.name$ duplicate$ "others" =
+ { 't := }
+ { pop$ }
+ if$
+ "," *
+ t "others" =
+ {
+
+ " " * bbl.etal *
+ }
+ { " " * t * }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ } if$
+}
+FUNCTION {format.authors}
+{ author "author" format.names
+}
+FUNCTION {get.bbl.editor}
+{ editor num.names$ #1 > 'bbl.editors 'bbl.editor if$ }
+
+FUNCTION {format.editors}
+{ editor "editor" format.names duplicate$ empty$ 'skip$
+ {
+ " " *
+ get.bbl.editor
+% capitalize
+ "(" swap$ * ")" *
+ *
+ }
+ if$
+}
+FUNCTION {format.note}
+{
+ note empty$
+ { "" }
+ { note #1 #1 substring$
+ duplicate$ "{" =
+ 'skip$
+ { output.state mid.sentence =
+ { "l" }
+ { "u" }
+ if$
+ change.case$
+ }
+ if$
+ note #2 global.max$ substring$ * "note" bibinfo.check
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title
+ duplicate$ empty$ 'skip$
+ { "t" change.case$ }
+ if$
+ "title" bibinfo.check
+}
+FUNCTION {output.bibitem}
+{ newline$
+ "\bibitem{" write$
+ cite$ write$
+ "}" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {n.dashify}
+{
+ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {word.in}
+{ bbl.in capitalize
+ ":" *
+ " " * }
+
+FUNCTION {format.date}
+{
+ month "month" bibinfo.check
+ duplicate$ empty$
+ year "year" bibinfo.check duplicate$ empty$
+ { swap$ 'skip$
+ { "there's a month but no year in " cite$ * warning$ }
+ if$
+ *
+ }
+ { swap$ 'skip$
+ {
+ swap$
+ " " * swap$
+ }
+ if$
+ *
+ remove.dots
+ }
+ if$
+ duplicate$ empty$
+ 'skip$
+ {
+ before.all 'output.state :=
+ " (" swap$ * ")" *
+ }
+ if$
+}
+FUNCTION {format.btitle}
+{ title "title" bibinfo.check
+ duplicate$ empty$ 'skip$
+ {
+ }
+ if$
+}
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ { bbl.volume volume tie.or.space.prefix
+ "volume" bibinfo.check * *
+ series "series" bibinfo.check
+ duplicate$ empty$ 'pop$
+ { emphasize ", " * swap$ * }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ { series field.or.null }
+ { output.state mid.sentence =
+ { bbl.number }
+ { bbl.number capitalize }
+ if$
+ number tie.or.space.prefix "number" bibinfo.check * *
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { bbl.in space.word *
+ series "series" bibinfo.check *
+ }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+FUNCTION {format.edition}
+{ edition duplicate$ empty$ 'skip$
+ {
+ output.state mid.sentence =
+ { "l" }
+ { "t" }
+ if$ change.case$
+ "edition" bibinfo.check
+ " " * bbl.edition *
+ }
+ if$
+}
+INTEGERS { multiresult }
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+FUNCTION {format.pages}
+{ pages duplicate$ empty$ 'skip$
+ { duplicate$ multi.page.check
+ {
+ bbl.pages swap$
+ n.dashify
+ }
+ {
+ bbl.page swap$
+ }
+ if$
+ tie.or.space.prefix
+ "pages" bibinfo.check
+ * *
+ }
+ if$
+}
+FUNCTION {format.journal.pages}
+{ pages duplicate$ empty$ 'pop$
+ { swap$ duplicate$ empty$
+ { pop$ pop$ format.pages }
+ {
+ ", " *
+ swap$
+ n.dashify
+ pages multi.page.check
+ 'titto.bbl.pages
+ 'titto.bbl.page
+ if$
+ swap$ tie.or.space.prefix
+ "pages" bibinfo.check
+ * *
+ *
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {format.journal.eid}
+{ eid "eid" bibinfo.check
+ duplicate$ empty$ 'pop$
+ { swap$ duplicate$ empty$ 'skip$
+ {
+ ", " *
+ }
+ if$
+ swap$ *
+ }
+ if$
+}
+FUNCTION {format.vol.num.pages} % this function is used only for journal entries
+{ volume field.or.null embolden
+ duplicate$ empty$ 'skip$
+ {
+% bbl.volume swap$ tie.or.space.prefix
+ titto.bbl.volume swap$ titto.space.prefix
+% rationale for the change above: for journals you don't want "vol." label
+% hence it does not make sense to attach the journal number to the label when
+% it is short
+ "volume" bibinfo.check
+ * *
+ }
+ if$
+ number "number" bibinfo.check duplicate$ empty$ 'skip$
+ {
+ swap$ duplicate$ empty$
+ { "there's a number but no volume in " cite$ * warning$ }
+ 'skip$
+ if$
+ swap$
+ "(" swap$ * ")" *
+ }
+ if$ *
+ eid empty$
+ { format.journal.pages }
+ { format.journal.eid }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { bbl.chapter }
+ { type "l" change.case$
+ "type" bibinfo.check
+ }
+ if$
+ chapter tie.or.space.prefix
+ "chapter" bibinfo.check
+ * *
+ pages empty$
+ 'skip$
+ { ", " * format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.booktitle}
+{
+ booktitle "booktitle" bibinfo.check
+}
+FUNCTION {format.in.ed.booktitle}
+{ format.booktitle duplicate$ empty$ 'skip$
+ {
+% editor "editor" format.names.ed duplicate$ empty$ 'pop$ % changed by titto
+ editor "editor" format.names duplicate$ empty$ 'pop$
+ {
+ " " *
+ get.bbl.editor
+% capitalize
+ "(" swap$ * ") " *
+ * swap$
+ * }
+ if$
+ word.in swap$ *
+ }
+ if$
+}
+FUNCTION {empty.misc.check}
+{ author empty$ title empty$ howpublished empty$
+ month empty$ year empty$ note empty$
+ and and and and and
+ key empty$ not and
+ { "all relevant fields are empty in " cite$ * warning$ }
+ 'skip$
+ if$
+}
+FUNCTION {format.thesis.type}
+{ type duplicate$ empty$
+ 'pop$
+ { swap$ pop$
+ "t" change.case$ "type" bibinfo.check
+ }
+ if$
+}
+FUNCTION {format.tr.number}
+{ number "number" bibinfo.check
+ type duplicate$ empty$
+ { pop$ bbl.techrep }
+ 'skip$
+ if$
+ "type" bibinfo.check
+ swap$ duplicate$ empty$
+ { pop$ "t" change.case$ }
+ { tie.or.space.prefix * * }
+ if$
+}
+FUNCTION {format.article.crossref}
+{
+ key duplicate$ empty$
+ { pop$
+ journal duplicate$ empty$
+ { "need key or journal for " cite$ * " to crossref " * crossref * warning$ }
+ { "journal" bibinfo.check emphasize word.in swap$ * }
+ if$
+ }
+ { word.in swap$ * " " *}
+ if$
+ " \cite{" * crossref * "}" *
+}
+FUNCTION {format.crossref.editor}
+{ editor #1 "{vv~}{ll}" format.name$
+ "editor" bibinfo.check
+ editor num.names$ duplicate$
+ #2 >
+ { pop$
+ "editor" bibinfo.check
+ " " * bbl.etal
+ *
+ }
+ { #2 <
+ 'skip$
+ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ {
+ "editor" bibinfo.check
+ " " * bbl.etal
+ *
+ }
+ {
+ bbl.and space.word
+ * editor #2 "{vv~}{ll}" format.name$
+ "editor" bibinfo.check
+ *
+ }
+ if$
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {format.book.crossref}
+{ volume duplicate$ empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ pop$ word.in
+ }
+ { bbl.volume
+ capitalize
+ swap$ tie.or.space.prefix "volume" bibinfo.check * * bbl.of space.word *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ { series emphasize * }
+ if$
+ }
+ { key * }
+ if$
+ }
+ { format.crossref.editor * }
+ if$
+ " \cite{" * crossref * "}" *
+}
+FUNCTION {format.incoll.inproc.crossref}
+{
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { format.booktitle duplicate$ empty$
+ { "need editor, key, or booktitle for " cite$ * " to crossref " *
+ crossref * warning$
+ }
+ { word.in swap$ * }
+ if$
+ }
+ { word.in key * " " *}
+ if$
+ }
+ { word.in format.crossref.editor * " " *}
+ if$
+ " \cite{" * crossref * "}" *
+}
+FUNCTION {format.org.or.pub}
+{ 't :=
+ ""
+ address empty$ t empty$ and
+ 'skip$
+ {
+ t empty$
+ { address "address" bibinfo.check *
+ }
+ { t *
+ address empty$
+ 'skip$
+ { ", " * address "address" bibinfo.check * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {format.publisher.address}
+{ publisher "publisher" bibinfo.warn format.org.or.pub
+}
+
+FUNCTION {format.organization.address}
+{ organization "organization" bibinfo.check format.org.or.pub
+}
+
+FUNCTION {article}
+{ output.bibitem
+ format.authors "author" output.check
+ add.colon
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ {
+ journal
+ "journal" bibinfo.check
+ "journal" output.check
+ add.blank
+ format.vol.num.pages output
+ format.date "year" output.check
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+FUNCTION {book}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check
+ add.colon
+ }
+ { format.authors output.nonnull
+ add.colon
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ new.sentence
+ format.number.series output
+ format.publisher.address output
+ }
+ {
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+FUNCTION {booklet}
+{ output.bibitem
+ format.authors output
+ add.colon
+ new.block
+ format.title "title" output.check
+ new.block
+ howpublished "howpublished" bibinfo.check output
+ address "address" bibinfo.check output
+ format.date output
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check
+ add.colon
+ }
+ { format.authors output.nonnull
+ add.colon
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ {
+ format.bvolume output
+ format.chapter.pages "chapter and pages" output.check
+ new.block
+ new.sentence
+ format.number.series output
+ format.publisher.address output
+ }
+ {
+ format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ format.authors "author" output.check
+ add.colon
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.chapter.pages output
+ new.sentence
+ format.number.series output
+ format.publisher.address output
+ format.edition output
+ format.date "year" output.check
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.chapter.pages output
+ }
+ if$
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+FUNCTION {inproceedings}
+{ output.bibitem
+ format.authors "author" output.check
+ add.colon
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ new.sentence % added by titto
+ format.bvolume output
+ format.pages output
+ new.sentence
+ format.number.series output
+ publisher empty$
+ { format.organization.address output }
+ { organization "organization" bibinfo.check output
+ format.publisher.address output
+ }
+ if$
+ format.date "year" output.check
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+FUNCTION {conference} { inproceedings }
+FUNCTION {manual}
+{ output.bibitem
+ author empty$
+ { organization "organization" bibinfo.check
+ duplicate$ empty$ 'pop$
+ { output
+ address "address" bibinfo.check output
+ }
+ if$
+ }
+ { format.authors output.nonnull }
+ if$
+ add.colon
+ new.block
+ format.btitle "title" output.check
+ author empty$
+ { organization empty$
+ {
+ address new.block.checka
+ address "address" bibinfo.check output
+ }
+ 'skip$
+ if$
+ }
+ {
+ organization address new.block.checkb
+ organization "organization" bibinfo.check output
+ address "address" bibinfo.check output
+ }
+ if$
+ format.edition output
+ format.date output
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ add.colon
+ new.block
+ format.btitle
+ "title" output.check
+ new.block
+ bbl.mthesis format.thesis.type output.nonnull
+ school "school" bibinfo.warn output
+ address "address" bibinfo.check output
+ format.date "year" output.check
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ format.authors output
+ add.colon
+ title howpublished new.block.checkb
+ format.title output
+ howpublished new.block.checka
+ howpublished "howpublished" bibinfo.check output
+ format.date output
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+ empty.misc.check
+}
+FUNCTION {phdthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ add.colon
+ new.block
+ format.btitle
+ "title" output.check
+ new.block
+ bbl.phdthesis format.thesis.type output.nonnull
+ school "school" bibinfo.warn output
+ address "address" bibinfo.check output
+ format.date "year" output.check
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ editor empty$
+ { organization "organization" bibinfo.check output
+ }
+ { format.editors output.nonnull }
+ if$
+ add.colon
+ new.block
+ format.btitle "title" output.check
+ format.bvolume output
+ editor empty$
+ { publisher empty$
+ { format.number.series output }
+ {
+ new.sentence
+ format.number.series output
+ format.publisher.address output
+ }
+ if$
+ }
+ { publisher empty$
+ {
+ new.sentence
+ format.number.series output
+ format.organization.address output }
+ {
+ new.sentence
+ format.number.series output
+ organization "organization" bibinfo.check output
+ format.publisher.address output
+ }
+ if$
+ }
+ if$
+ format.date "year" output.check
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ format.authors "author" output.check
+ add.colon
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ institution "institution" bibinfo.warn output
+ address "address" bibinfo.check output
+ format.date "year" output.check
+% new.block
+ format.doi output
+ format.url output
+% new.block
+ format.note output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ format.authors "author" output.check
+ add.colon
+ new.block
+ format.title "title" output.check
+ format.date output
+% new.block
+ format.url output
+% new.block
+ format.note "note" output.check
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+READ
+FUNCTION {sortify}
+{ purify$
+ "l" change.case$
+}
+INTEGERS { len }
+FUNCTION {chop.word}
+{ 's :=
+ 'len :=
+ s #1 len substring$ =
+ { s len #1 + global.max$ substring$ }
+ 's
+ if$
+}
+FUNCTION {sort.format.names}
+{ 's :=
+ #1 'nameptr :=
+ ""
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr
+ "{ll{ }}{ ff{ }}{ jj{ }}"
+ format.name$ 't :=
+ nameptr #1 >
+ {
+ " " *
+ namesleft #1 = t "others" = and
+ { "zzzzz" * }
+ { t sortify * }
+ if$
+ }
+ { t sortify * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+ "A " #2
+ "An " #3
+ "The " #4 t chop.word
+ chop.word
+ chop.word
+ sortify
+ #1 global.max$ substring$
+}
+FUNCTION {author.sort}
+{ author empty$
+ { key empty$
+ { "to sort, need author or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+FUNCTION {author.editor.sort}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { "to sort, need author, editor, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+FUNCTION {author.organization.sort}
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need author, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { "The " #4 organization chop.word sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+FUNCTION {editor.organization.sort}
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need editor, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { "The " #4 organization chop.word sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+FUNCTION {presort}
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.sort
+ { type$ "proceedings" =
+ 'editor.organization.sort
+ { type$ "manual" =
+ 'author.organization.sort
+ 'author.sort
+ if$
+ }
+ if$
+ }
+ if$
+ " "
+ *
+ year field.or.null sortify
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+ITERATE {presort}
+SORT
+STRINGS { longest.label }
+INTEGERS { number.label longest.label.width }
+FUNCTION {initialize.longest.label}
+{ "" 'longest.label :=
+ #1 'number.label :=
+ #0 'longest.label.width :=
+}
+FUNCTION {longest.label.pass}
+{ number.label int.to.str$ 'label :=
+ number.label #1 + 'number.label :=
+ label width$ longest.label.width >
+ { label 'longest.label :=
+ label width$ 'longest.label.width :=
+ }
+ 'skip$
+ if$
+}
+EXECUTE {initialize.longest.label}
+ITERATE {longest.label.pass}
+FUNCTION {begin.bib}
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+ "\begin{thebibliography}{" longest.label * "}" *
+ write$ newline$
+ "\providecommand{\url}[1]{\texttt{#1}}"
+ write$ newline$
+ "\providecommand{\urlprefix}{URL }"
+ write$ newline$
+ "\providecommand{\doi}[1]{https://doi.org/#1}"
+ write$ newline$
+}
+EXECUTE {begin.bib}
+EXECUTE {init.state.consts}
+ITERATE {call.type$}
+FUNCTION {end.bib}
+{ newline$
+ "\end{thebibliography}" write$ newline$
+}
+EXECUTE {end.bib}
+%% End of customized bst file
+%%
+%% End of file `titto.bst'.