summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/dbshow
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/dbshow')
-rw-r--r--macros/latex/contrib/dbshow/dbshow-doc.pdfbin388176 -> 373472 bytes
-rw-r--r--macros/latex/contrib/dbshow/dbshow-doc.tex1135
-rw-r--r--macros/latex/contrib/dbshow/dbshow.sty421
3 files changed, 1051 insertions, 505 deletions
diff --git a/macros/latex/contrib/dbshow/dbshow-doc.pdf b/macros/latex/contrib/dbshow/dbshow-doc.pdf
index fd03985433..c6d4b714d4 100644
--- a/macros/latex/contrib/dbshow/dbshow-doc.pdf
+++ b/macros/latex/contrib/dbshow/dbshow-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/dbshow/dbshow-doc.tex b/macros/latex/contrib/dbshow/dbshow-doc.tex
index 40bef33d17..ebfe69c535 100644
--- a/macros/latex/contrib/dbshow/dbshow-doc.tex
+++ b/macros/latex/contrib/dbshow/dbshow-doc.tex
@@ -1,5 +1,7 @@
\documentclass[full]{l3doc}
-\usepackage[scheme=plain]{ctex}
+\usepackage[scheme=plain, fontset=ubuntu]{ctex}
+\usepackage{multicol}
+\usepackage{adjustbox}
\usepackage{zhlineskip}
\usepackage{enumitem}
\usepackage{indentfirst}
@@ -11,22 +13,9 @@
\tcbuselibrary{listings, skins, raster, breakable}
\usepackage{tabularray}
-\def\zhdate{2022年1月8日}
-\def\endate{2022/01/08}
-\def\version{v1.2}
-
-\IndexPrologue
- {
- \section*{Index}
- \markboth{Index}{Index}
- \addcontentsline{toc}{section}{Index}
- The~italic~numbers~denote~the~pages~where~the~
- corresponding~entry~is~described,~
- numbers~underlined~point~to~the~definition,~
- all~others~indicate~the~places~where~it~is~used.
- }
-
-\newcommand\tikzmark[1]{\tikz \coordinate[overlay, remember picture] (#1);}
+\def\zhdate{2022年1月10日}
+\def\endate{2022/01/10}
+\def\version{v1.3}
\geometry{
left=4.5cm,
@@ -46,8 +35,39 @@
}
}
+\IndexPrologue {
+ \part*{Index}
+ \markboth{Index}{Index}
+ \addcontentsline{toc}{part}{Index}
+ The~italic~numbers~denote~the~pages~where~the~
+ corresponding~entry~is~described,~
+ numbers~underlined~point~to~the~definition,~
+ all~others~indicate~the~places~where~it~is~used.
+}
+
+\GlossaryPrologue {
+ \part*{Change~History}
+ {\GlossaryParms\ttfamily\hyphenchar\font=`\-}
+ \markboth{Change~History}{Change~History}
+ \addcontentsline{toc}{part}{Change~History}
+}
+
+\let\subsubitem\subitem
+
\DoNotIndex{\begin, \end}
\setlength{\parskip}{\medskipamount}
+
+\newcommand\tikzmark[1]{\tikz \coordinate[overlay, remember picture] (#1);}
+\def\levelchar{?}
+\def\orbar{\textup{\textbar}}
+\def\defaultval#1{\textbf{\textup{#1}}}
+\def\TF{true\orbar false}
+\def\TTF{\defaultval{true}\orbar false}
+\def\TFF{true\orbar\defaultval{false}}
+\def\zhbefore{\textbf{前}}
+\def\zhafter{\textbf{后}}
+\def\enbefore{\textbf{before}~}
+\def\enafter{\textbf{after}~}
\DeclareDocumentEnvironment { note } { +b } {
\par\textbf{\textsf{NOTE:~}}#1\par
} {}
@@ -59,32 +79,55 @@
top=2cm,
bottom=2cm
}
+ \PrintChanges
\PrintIndex
}
\ExplSyntaxOn
-\NewDocumentCommand { \strcs } { m } {
- \texttt{\tl_to_str:n { #1 }}
+\makeatletter
+\cs_new_protected:Nn \dbshow_changes:nnnn {
+ \@bsphack\group_begin:\@sanitize
+ \catcode`\\\z@ \catcode`\ 10 \MakePercentIgnore
+ \exp_args:Nx \glossary {
+ \exp_not:N \textbf{#1}\levelchar
+ \exp_not:N \textit{#2}\c_space_tl
+ \exp_not:N \textbf{#3}\c_colon_str\c_space_tl
+ \exp_not:n { #4 }
+ }
+ \group_end:\@esphack
}
-
-\dim_new:N \l__my_syntax_dim
-\box_new:N \g__my_syntax_box
-\NewDocumentEnvironment { Syntax } { s }
- {
- \dim_set:Nn \l__my_syntax_dim
- { \textwidth }
- \hbox_gset:Nw \g__my_syntax_box
- \small \ttfamily
- \begin{minipage}[t]{\l__my_syntax_dim}
- \raggedright\obeyspaces\obeylines
+\cs_generate_variant:Nn \dbshow_changes:nnnn { xnnn }
+
+\cs_new_protected:Nn \dbshow_changes_what:nnnn {
+ \regex_extract_once:nnNT { doc|macro|bug|option }
+ { #3 } \l_tmpa_seq {
+ \dbshow_changes:xnnn {
+ \str_case_e:nn { \seq_item:Nn \l_tmpa_seq { 1 } } {
+ { doc } { Documentation }
+ { macro } { Macro }
+ { bug } { Bug }
+ { option } { Option }
+ { logic } { Logic }
+ }
+ }
+ {#2} {#3} {#4}
}
- {
- \end{minipage}
- \hbox_gset_end:
- \IfValueF { #1 } { \smallskip }
- \box_use_drop:N \g__my_syntax_box
- \smallskip
+}
+
+\cs_new_protected:Nn \dbshow_changes_how:nnnn {
+ \regex_extract_once:nnNT { Add|Update|Remove } { #3 } \l_tmpa_seq {
+ \dbshow_changes:xnnn { \seq_item:Nn \l_tmpa_seq { 1 } }
+ {#2} {#3} {#4}
}
+}
+
+% #1 version #2 date #3 type #4 desc
+\DeclareDocumentCommand \changes { m m m m } {
+ \dbshow_changes:nnnn {#1} {#2} {#3} {#4}
+ \dbshow_changes_what:nnnn {#1} {#2} {#3} {#4}
+ \dbshow_changes_how:nnnn {#1} {#2} {#3} {#4}
+}
+\makeatother
\DeclareDocumentEnvironment { Description } { o +b } {
\hbox_set:Nn \l_tmpa_box { #1 }
@@ -94,35 +137,38 @@
\end{itemize}
} { }
-\keys_define:nn { dbshow/doc } {
- opt .tl_set:N = \l_opt_tl,
- desc .tl_set:N = \l_desc_tl,
- init .tl_set:N = \l_init_tl,
- init .initial:n = init-none,
+\cs_new_protected:Nn \dbshowdoc_function_begin:N {
+ \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 }
+ {##1} { \adjustbox{width=.7\marginparwidth, height=\box_ht:N \l_tmpa_box}{##1} }
+ #1{##1}
+ \__codedoc_typeset_expandability: \\
+ }
}
-
-\box_new:N \l__option_box
-\NewDocumentEnvironment { option } { m +b } {
- \keys_set:nn { dbshow/doc } { #1 }
- \hbox_set:Nw \l__option_box
- \small \ttfamily
- \begin{minipage}[t]{\textwidth}
- \obeyspaces\obeylines
- \textcolor{red}{
- \l_opt_tl
- \exp_args:Nx\SpecialOptionIndex{\l_opt_tl}
- }
- {~}\l_desc_tl
- \hfill(
- \tl_if_eq:NnTF \l_init_tl { init-none } { no~value }
- { initially~\texttt{\l_init_tl} }
- )
- \end{minipage}
- \hbox_gset_end:
- \box_use_drop:N \l__option_box
- #2
- \medskip
-} { }
+\cs_new_protected:Nn \dbshowdoc_function_end: {
+ \cs_set_eq:NN \__codedoc_typeset_function_block:nN \__codedoc_tmp_cs:nN
+}
+\DeclareDocumentEnvironment { option } { O{} +v }
+ {
+ \dbshowdoc_function_begin:N \SpecialOptionIndex
+ \__codedoc_function:nnw {#1} {#2}
+ }
+ {
+ \__codedoc_function_end:
+ \dbshowdoc_function_end:
+ }
+\DeclareDocumentEnvironment { environment } { O{} +v }
+ {
+ \dbshowdoc_function_begin:N \SpecialEnvIndex
+ \__codedoc_function:nnw {#1} {#2}
+ }
+ {
+ \__codedoc_function_end:
+ \dbshowdoc_function_end:
+ }
\DeclareDocumentCommand \opt { O{} m }
{ \__codedoc_cmd:no {#1} { #2 } }
@@ -163,13 +209,23 @@
和其他数据库宏包比如 \pkg{datatool} 相比,\pkg{dbshow} 更专注于非图表类型的数
据展示。
+\changes{1.2}{2022-01-09}{Add doc}{descripton for expansion}
+\begin{itemize}
+ \item 名字后带有 $\star$ 的命令是可以完全展开的(fully-expandable);
+ \item 名字后带有 \ding{73} 的命令可以有限制地展开(restricted-expandable);
+ \item 名字后不带有特殊字符的命令是不可展开的(non-expandable);
+ \item 名字后带有 $\star$ 的选项不影响相关的代码的是否可展开;
+ \item 名字后带有 \ding{73} 的选项是否影响相关代码的可展开性取决于选项的设置;
+ \item 名字后不带有特殊字符的选项会使与之相关的代码变得不可展开。
+\end{itemize}
+
\subsection{数据类型}
宏包基于 \pkg{expl3} 的基础类型构建了6种类型:
\begin{Description}[\texttt{clist}]
\item[\texttt{date}]
- 基于宏包 \pkg{datetime2} 的日期类型,以iso标准存储,支持大小比较,排序(转
- 换成字符串)。默认值为 \cs{Today}。
+ 日期类型,以 |yyyy/mm/dd| 形式存储,支持大小比较,排序(转
+ 换成字符串)。默认值为 \cs{dbtoday}。
\item[\texttt{str}]
字符串类型,支持正则匹配,英文排序。默认值为空。
\item[\texttt{tl}]
@@ -182,8 +238,14 @@
逗号分隔的列表类型。默认值为空列表。
\end{Description}
+\changes{1.3}{2022-01-08}{Remove dependency}{\pkg{datatime2}}
+除了日期类型,所有类型都是 \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} 实现,支持字符串的正则匹配,还支持多级排序。使用
方式上更倾向于样式与内容分离,所有的样式都可以通过选项提前定义好并且可以复用。
@@ -197,7 +259,7 @@
\section{接口文档}
\subsection{创建、展示和清空数据库}
-\begin{function}{\dbNewDatabase, \dbNewDatabase*}
+\begin{function}[added=2022-01-05]{\dbNewDatabase, \dbNewDatabase*}
\begin{syntax}
\cs{dbNewDatabase} \oarg{base database} \marg{database} \{ \\
~~\meta{attr1} = \meta{type spec1}, \\
@@ -226,7 +288,7 @@
}
\meta{attr} = \meta{type} &
将 \meta{attr} 声明为 \meta{type} 类型 \\
- \meta{attr} = \meta{type}\textbar\meta{default} &
+ \meta{attr} = \meta{type}\orbar\meta{default} &
将 \meta{attr} 声明为 \meta{type} 类型,并且将默认值设置为 \meta{default}。
\\
\end{tblr}
@@ -247,7 +309,7 @@
}
\end{verbatim}
-\begin{function}{\dbshow}
+\begin{function}[added=2022-01-05]{\dbshow}
\begin{syntax}
\cs{dbshow} \marg{style} \marg{database}
\end{syntax}
@@ -255,18 +317,17 @@
使用 \meta{style} 样式来展示 \meta{database}。
\end{function}
-\begin{function}{\dbclear}
+\changes{1.2}{2022-01-07}{Add macro}{\cs{dbclear}}
+\begin{function}[added=2022-01-07]{\dbclear}
\begin{syntax}
\cs{dbclear} \marg{database}
\end{syntax}
-
清空 \meta{database} 里的所有内容。
-
\end{function}
\subsection{\cs{dbNewStyle} 和样式选项}
-\begin{function}{\dbNewStyle}
+\begin{function}[added=2022-01-05]{\dbNewStyle}
\begin{syntax}
\cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts}
\end{syntax}
@@ -277,14 +338,25 @@
\subsubsection{通用选项}
-\begin{option}{opt=filter, desc={= \meta{filter}}, init=-none-}
+\begin{option}[added=2022-01-05]{filter}
+ \begin{syntax}
+ filter = <filter>
+ \end{syntax}
+
为当前样式设置由 \cs{dbCombineFilters} 所定义的过滤器
\end{option}
-\begin{option}{opt=raw-filter, desc={= \meta{cond combination}}}
- 用已定义的条件为当前样式设置匿名过滤器。下面两个例子的作用是等同的。
+\begin{option}[added=2022-01-06]{raw-filter}
+ \begin{syntax}
+ raw-filter = <conditional expression>
+ \end{syntax}
+
+ 使用条件表达式设置匿名过滤器,这里的条件指通过 \cs{dbNewConditional} 定义的
+ 条件。下面代码中两个示例的过滤器具有相同的功能。
\end{option}
+\changes{1.1}{2022-01-06}{Add option}{\opt{raw-filter}}
+
\begin{verbatim}
% method 1
\begin{dbFilters}{db}
@@ -301,10 +373,12 @@
\dbNewStyle{style}{db}{filter=filter}
\end{verbatim}
-\begin{option}{
- opt = sort,
- desc = {= \{ \meta{attr spec1}, \meta{attr spec2}, \ldots{} \}},
-}
+\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{} \}
+ \end{syntax}
+
为当前样式设置排序规则。支持根据 |str|,|date|,|int|,|fp| 类型的数据进行排
序,支持多级排序。\meta{attr} 表示增序,\meta{attr}* 表示降序。下面例子中,
使用 |sort-style| 展示数据时的顺序为先按 |level| 降序,|level| 相同的再按出
@@ -323,34 +397,74 @@
}
\end{verbatim}
-\begin{option}{
- opt = item-code,
- desc = {= \meta{item code}}
-}
+\begin{option}[added=2022-01-05, rEXP]{item-code}
+ \begin{syntax}
+ item-code = <code>
+ \end{syntax}
+
该选项用来设置展示数据库中每条记录的代码。你可以使用 \cs{dbuse} 来展示属性的
值。
\end{option}
-\begin{option}{
- opt = {\meta{attr}/sep},
- desc = {= \meta{sep spec}},
- init = {,~\~}
-}
-\begin{Syntax}
- \meta{attr}/sep = \meta{separator} \\
- \meta{attr}/sep = \{ \\
- ~~\meta{separator between two}, \\
- ~~\meta{separator between more than two}, \\
- ~~\meta{separator between final two} \\
- \}
-\end{Syntax}
-
- 该选项只适用于类型为 |clist| 的属性,用来设置列表间元素的间隔。第一个版本接
- 受一个参数,将所有的元素间隔设置为 \meta{separator}。第二个版本接受逗号分隔
- 的三个参数,分别用来设置只有两个元素时的分隔符 \meta{separator between two},
- 超过两个元素时的分隔符 \meta{separator between more than two},和最后两个元
- 素之间的分隔符 \meta{separator between final two}。
+\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}
+ <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} \\
+ \} \\
+ \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会触发报错。
+\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}
+
+\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}}
+\begin{option}[added=2022-01-08, EXP]{<attr>/zfill}
+ \begin{syntax}
+ <attr>/zfill = <\TTF>
+ \end{syntax}
+
+ 该选项只适用于类型为 |date| 的属性。控制输出月份和天时是否补零。
\end{option}
\subsubsection{装饰器}
@@ -385,69 +499,90 @@
}
\end{verbatim}
-\begin{option}{
- opt = before-code,
- desc = {= \meta{before code}}
-}
- 该选项用来设置在展示整个数据库之前需要执行的代码。
+\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}}
+\begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper}
+ \begin{syntax}
+ <attr>/wrapper = <control sequence>
+ \end{syntax}
+
+ 该选项只适用于类型为 |date| 的属性。\meta{control sequence} 只接收一个参数即
+ 日期,如果设置了此选项,则最后输出的日期为
+ \meta{control sequence}\marg{date}。
\end{option}
-\begin{option}{
- opt = after-code,
- desc = {= \meta{after code}}
-}
- 该选项用来设置在展示整个数据库之后需要执行的代码。
+\begin{option}[added=2022-01-05, rEXP]{before-code}
+ \begin{syntax}
+ before-code = <code>
+ \end{syntax}
+
+ 该选项用来设置在展示整个数据库之\zhbefore 需要执行的代码。
\end{option}
-\begin{option}{
- opt = record-before-code,
- desc = {= \meta{before code}}
-}
- 该选项用来设置在展示当前记录之前需要执行的代码。
+\begin{option}[added=2022-01-05, rEXP]{after-code}
+ \begin{syntax}
+ after-code = <code>
+ \end{syntax}
+
+ 该选项用来设置在展示整个数据库之\zhafter 需要执行的代码。
\end{option}
-\begin{option}{
- opt = record-after-code,
- desc = {= \meta{after code}}
-}
- 该选项用来设置在展示当前记录之后需要执行的代码。
+\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}
+ \begin{syntax}
+ record-before-code = <code>
+ \end{syntax}
+
+ 该选项用来设置在展示当前记录之\zhbefore 需要执行的代码。
\end{option}
-\begin{option}{
- opt = {\meta{attr}/before-code},
- desc = {= \meta{before code}}
-}
- 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之前需要执行的代码。
- \cs{dbuse} 会在展示属性数据前执行此代码。
+\begin{option}[added=2022-01-05, rEXP]{record-after-code}
+ \begin{syntax}
+ record-after-code = <code>
+ \end{syntax}
+
+ 该选项用来设置在展示当前记录之\zhafter 需要执行的代码。
\end{option}
-\begin{option}{
- opt = {\meta{attr}/after-code},
- desc = {= \meta{after code}}
-}
- 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之后需要执行的代码。
- \cs{dbuse} 会在展示属性数据后执行此代码。
+\begin{option}[added=2022-01-05, rEXP]{<attr>/before-code}
+ \begin{syntax}
+ <attr>/before-code = <code>
+ \end{syntax}
+
+ 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhbefore 需要执行的代
+ 码。\cs{dbuse} 会在展示属性数据\zhbefore 执行此代码。
\end{option}
-\begin{option}{
- opt = {\meta{attr}/item-before-code},
- desc = {= \meta{before code}}
-}
- 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素前需要执行的代
- 码。
+\begin{option}[added=2022-01-05, rEXP]{<attr>/after-code}
+ \begin{syntax}
+ <attr>/after-code = <code>
+ \end{syntax}
+
+ 该选项用来设置展示数据库中属性 \meta{attr} 对应数据之\zhafter 需要执行的代码。
+ \cs{dbuse} 会在展示属性数据\zhafter 执行此代码。
\end{option}
-\begin{option}{
- opt = {\meta{attr}/item-after-code},
- desc = {= \meta{after code}}
-}
- 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素后需要执行的代
- 码。
+\begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code}
+ \begin{syntax}
+ <attr>/item-before-code = <code>
+ \end{syntax}
+
+ 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhbefore 需要
+ 执行的代码。
+\end{option}
+
+\begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code}
+ \begin{syntax}
+ <attr>/item-after-code = <code>
+ \end{syntax}
+
+ 该选项只适用于类型为 |clist| 的属性,用来设置展示列表每个元素\zhafter 需要执
+ 行的代码。
\end{option}
\subsection{使用 \cs{dbNewReviewPoints} 定义复习点}
-\begin{function}{\dbNewReviewPoints}
+\begin{function}[added=2022-01-05]{\dbNewReviewPoints}
\begin{syntax}
\cs{dbNewReviewPoints} \marg{name} \marg{points}
\end{syntax}
@@ -455,6 +590,8 @@
定义名为 \meta{name} 的复习点。这是专门为错题本或复习所定制的功能,
\meta{points}是一系列整数,现在假设每道错题你都将写错时的日期记录在了 |date|
属性中,并且你希望每隔2,5,15天复习一次。下面的代码给出了一个实现示例。
+\end{function}
+
\begin{verbatim}
\dbNewReviewPoints{review-point}{2, 5, 15} % 定义复习点
\begin{dbFilters}
@@ -463,47 +600,52 @@
\end{dbFilters}
\dbNewStyle{review-style}{ques}{filter=filter1} % 定义展示样式
\end{verbatim}
-\end{function}
\subsection{在 \env{dbFilters} 环境中定义过滤器}
-\noindent\DescribeEnv{dbFilters}
-\begin{Syntax}*
- |\begin{dbFilters}|\marg{database} \\
- ~~\meta{code}
- |\end{dbFilters}| \\
-\end{Syntax}
+\begin{environment}[added=2022-01-05]{dbFilters}
+ \begin{syntax}
+ |\begin{dbFilters}|\marg{database} \\
+ ~~\meta{code}
+ |\end{dbFilters}| \\
+ \end{syntax}
-\env{dbFilters}用来定义过滤器,此环境中定义了 \cs{dbNewConditional} 命令用来定
-义条件和 \cs{dbCombineConditionals} 命令用来组合条件定义过滤器。过滤器独立于每
-个 \meta{database},这意味着你可以在不同数据库中定义名称相同的过滤条件和过滤器。
+ \env{dbFilters}用来定义过滤器,此环境中定义了 \cs{dbNewConditional} 命令用来
+ 定义条件和 \cs{dbCombineConditionals} 命令用来组合条件定义过滤器。过滤器独立
+ 于每个 \meta{database},这意味着你可以在不同数据库中定义名称相同的过滤条件和
+ 过滤器。
+\end{environment}
-\begin{function}{\dbNewConditional, \dbNewConditional*}
+\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*}
\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{relation} \\
- \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{relation} \\
+ \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} \{\meta{review points}\textbar\meta{date}\} \\
- \cs{dbNewConditional}* \marg{name} \marg{date attr} \marg{relation}
+ \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr}
+ \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\
\end{syntax}
\cs{dbNewConditional} 用来定义名为 \meta{name} 的条件,\meta{attr} 指定条件
所绑定的属性,在 \meta{cond spec} 中可以用 \cs{dbval} 指代属性的值。
\end{function}
- 对于类型为 |int| 和 |fp| 的属性,两个版本的定义是一致的,\meta{relation} 可
- 以是单个关系式,比如 |\dbval > 3|,也可以是组合关系式,比如
- |\dbval > 3 && \dbval < 10.2|。支持的操作符有 |<, >, =, ==, !=, >=, <=, !|。
+ \changes{1.3}{2022-01-10}{Update doc}{truncated division}
+ 对于类型为 |int| 和 |fp| 的属性,\meta{expr} 传递给 \cs{int_compare:nTF} 或
+ \cs{fp_compare:nTF} 处理。
+ \begin{note}
+ |/| 为四舍五入除法,截断除法请用 \cs{dbIntDivTruncate}。
+ \end{note}
对于类型为 |str| 和 |tl| 的属性,\meta{regex} 为正则表达式,
\cs{dbNewConditional} 表示部分匹配,\cs{dbNewConditional*} 表示整体匹配。
+
\begin{verbatim}
- \dbNewConditional{cond1}{str-attr}{abc} % 匹配 abc, abcd, 1abc, =abc= 等
+ \dbNewConditional {cond1}{str-attr}{abc} % 匹配 abc, abcd, 1abc, =abc= 等
\dbNewConditional*{cond2}{str-attr}{abc} % 只匹配 abc
\end{verbatim}
@@ -513,16 +655,19 @@
(列表)中条件才成立。
\begin{verbatim}
- \dbNewConditional{cond1}{clist-attr}{a, b, c} % a, b, d 满足条件
+ \dbNewConditional {cond1}{clist-attr}{a, b, c} % a, b, d 满足条件
\dbNewConditional*{cond2}{clist-attr}{a, b, c} % a, b, d 不满足条件
\end{verbatim}
- 对于类型为 |date| 的属性,\cs{dbNewConditional} 使用复习点来定义过滤条件,
- \meta{review points} 是 \cs{dbNewReviewPoints} 定义的复习点,\meta{date} 是
- 用来比较的日期;\cs{dbNewConditional*} 使用\textbf{单个}关系式来定义过滤条件。
- 支持的操作符有 |<, >, =, ==, !=, >=, <=|。
+ \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} 是用来比较的日期。
-\begin{function}{\dbCombineConditionals}
+\begin{function}[added=2022-01-05]{\dbCombineConditionals}
\begin{syntax}
\cs{dbCombineConditionals} \marg{name} \marg{cond combination} \oarg{info}
\end{syntax}
@@ -537,51 +682,56 @@
\subsection{使用 \env{dbitem} 环境存储数据}
-\noindent\DescribeEnv{dbitem}
-\begin{Syntax}*
- |\begin{dbitem}|\marg{database}[ \\
- ~~\meta{attr1} = \meta{val1}, \\
- ~~\meta{attr2} = \meta{val2}, \\
- ~~\ldots{} \\
- ] \\
- ~~\meta{code} \\
- |\end{dbitem}|
-\end{Syntax}
+\begin{environment}[added=2022-01-05]{dbitem}
+ \begin{syntax}
+ |\begin{dbitem}|\marg{database}[ \\
+ ~~\meta{attr1} = \meta{val1}, \\
+ ~~\meta{attr2} = \meta{val2}, \\
+ ~~\ldots{} \\
+ ] \\
+ ~~\meta{code} \\
+ |\end{dbitem}|
+ \end{syntax}
\env{dbitem} 环境用来存储数据。有两种存储数据的方法,较短的数据可以在选项列
表中通过键值对设置值,较长的数据可以在 \meta{code} 中使用 \cs{dbsave} 存储。
\cs{dbsave}会覆盖选项中设置的值。没有设置的值将会被设置为全局默认值,下面给
出一个存储示例。
+\end{environment}
\begin{verbatim}
- \begin{dbitem}[date=2022-01-01, info=测试]
+ \begin{dbitem}[date = 2022-01-01, info = 测试]
\dbsave{question}{这是一个测试问题}
- \dbsave{answer}{这是一个测试答案}
+ \dbsave{answer} {这是一个测试答案}
\end{dbitem}
\end{verbatim}
\subsection{\cs{dbsave} 和 \cs{dbuse}}
-\begin{function}{\dbsave}
+\changes{1.3}{2022-01-08}{Add macro}{\cs{dbsave*}}
+\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbsave, \dbsave*}
\begin{syntax}
- \cs{dbsave} \marg{attr} \marg{data}
+ \cs{dbsave} \marg{attr} \marg{data} \\
+ \cs{dbsave}* \marg{attr} \marg{data}
\end{syntax}
- \cs{dbsave} 用来存储数据,只能在 \env{item} 环境中使用。
+ \cs{dbsave} 用来存储数据,只能在 \env{item} 环境中使用。使用 \cs{dbsave*} 存
+ 储的数据会被 \cs{exp_not:n} 包裹。
\end{function}
-\begin{function}[EXP]{\dbuse}
+\changes{1.2}{2022-01-08}{Update macro}{make \cs{dbuse} fully-expandable}
+\begin{function}[added=2022-01-05, updated=2022-01-08, EXP]{\dbuse}
\begin{syntax}
- \cs{dbuse} \marg{attr}
+ \cs{dbuse} \marg{attr}
\end{syntax}
- \cs{dbuse} 用来使用数据,只能在 \opt{item-code} 选项中使用。\cs{dbuse} 是可
+ \cs{dbuse} 用来展示数据,只能在 \opt{item-code} 选项中使用。\cs{dbuse} 是可
展开的。
\end{function}
\subsection{条件判别式}
-\begin{function}[EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF}
+\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} \\
@@ -599,33 +749,68 @@
}
\end{verbatim}
-\subsection{特殊命令}
-
-\pkg{dbshow} 定义了一些特殊的命令,会根据语境展开为不同的内容。
-
-\DescribeMacro{\dbval}当前属性的值,只能在 \cs{dbNewConditional} 中使用
+\changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}}
-\DescribeMacro{\dbDatabase}数据库名称
+\subsection{表达式函数}
-\DescribeMacro{\dbFilterName}过滤器名称
-
-\DescribeMacro{\dbFilterInfo}过滤器信息
-
-\DescribeMacro{\dbIndex}原始数据索引,等同于 |\dbuse{id}| 但是 \cs{dbuse} 是不可展开的
-
-\DescribeMacro{\dbarabic}用数字表示的查询集数据计数
-
-\DescribeMacro{\dbalph}用小写字母表示的查询集数据计数
+\changes{1.3}{2022-01-10}{Add macros}{expression function aliases}
+\begin{function}[added=2022-01-10, EXP]{
+ \dbIntAbs, \dbIntSign, \dbIntDivRound, \dbIntDivTruncate, \dbIntMax,
+ \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} \\
+\end{function}
-\DescribeMacro{\dbAlph}用小写字母表示的查询集数据计数
+\subsection{特殊命令}
-\DescribeMacro{\dbroman}用小写罗马数字表示的查询集数据计数
+\pkg{dbshow} 定义了一些特殊的命令,会根据语境展开为不同的内容。
-\DescribeMacro{\dbRoman}用大写罗马数字表示的查询集数据计数
+\changes{1.1}{2022-01-05}{Add macro}{
+ \cs{dbarabic}, \cs{dbalph}, \cs{dbAlph}, \cs{dbroman},
+ \cs{dbRoman}
+}
+\changes{1.1}{2022-01-06}{Fix bug}{\cs{dbIndex} not defined}
+\begin{function}[added=2022-01-05, EXP]{
+ \dbval, \dbDatabase, \dbFilterName, \dbFilterInfo,
+ \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman
+}
+\begin{tblr}{ll}
+ \cs{dbval} & 当前属性的值 \\
+ \cs{dbDatabase} & 数据库名称 \\
+ \cs{dbFilterName} & 当前样式过滤器的名称 \\
+ \cs{dbFilterInfo} & 当前样式过滤器的相关信息 \\
+ \cs{dbIndex} & 数据索引,等同于 \cs{dbuse}|{id}| \\
+ \cs{dbarabic} & 用数字表示的查询集数据计数 \\
+ \cs{dbalph} & 用小写字母表示的查询集数据计数 \\
+ \cs{dbAlph} & 用大写字母表示的查询集数据计数 \\
+ \cs{dbroman} & 用小写罗马字母表示的查询集数据计数 \\
+ \cs{dbroman} & 用大写罗马字母表示的查询集数据计数 \\
+ \end{tblr}
+\end{function}
\section{错题本示例}
见第 \ref{sec:example} 节。
+\changes{1.1}{2022-01-07}{Update doc}{improve example}
+
\title{
Package \pkg{dbshow} \version%
\protect\footnote{%
@@ -653,13 +838,26 @@ The package provides four core functions: data storage and display, 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.
+\changes{1.2}{2022-01-09}{Add doc}{descripton for expansion}
+\begin{itemize}
+ \item Macros with a $\star$ are fully-expandable;
+ \item Macros with a \ding{73} are restricted-expandable;
+ \item Macros without appending a special symbol are nonexpandable;
+ \item Options with a $\star$ \textit{do not} affect the expandability of
+ related macros;
+ \item Options with a \ding{73} affect the expandability of related macros
+ according to its value;
+ \item Options without appending a special symbol make the related macros
+ nonexpandable.
+\end{itemize}
+
\subsection{Data Types}
The package constructs 6 types based on the internal typed of \pkg{expl3}:
\begin{Description}[\texttt{clist}]
\item[\texttt{date}]
- date based on \pkg{datetime2} in iso format, supports comparison,
- sorting (converting to |str|), default \cs{Today}.
+ date saved in |yyyy/mm/dd| format, supports comparison, sorting
+ (converting to string), default \cs{dbtoday}.
\item[\texttt{str}]
string,supports regex match and sorting, default empty.
\item[\texttt{tl}]
@@ -672,8 +870,15 @@ The package constructs 6 types based on the internal typed of \pkg{expl3}:
comma list, default empty.
\end{Description}
+\changes{1.3}{2022-01-08}{Remove dependency}{\pkg{datatime2}}
+All types are internal types of \pkg{expl3} except |date| type, which provides
+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
@@ -692,7 +897,7 @@ persistence.
\subsection{Create, Display and Clear Database}
-\begin{function}{\dbNewDatabase, \dbNewDatabase*}
+\begin{function}[added=2022-01-05]{\dbNewDatabase, \dbNewDatabase*}
\begin{syntax}
\cs{dbNewDatabase} \oarg{base database} \marg{database} \{ \\
~~\meta{attr1} = \meta{type spec1}, \\
@@ -713,10 +918,10 @@ Create a new database named \meta{database}, unstarred form provides the optiona
The unstarred form always replace the old definition, while starred form
appends the new options.
-\begin{Syntax}
+\begin{syntax}
\meta{attr} = \meta{type} \\
- \meta{attr} = \meta{type}\textbar\meta{default}
-\end{Syntax}
+ \meta{attr} = \meta{type}\orbar\meta{default}
+\end{syntax}
The first form defines the \meta{attr} as \meta{type}, and the second also
sets the default value.
@@ -736,7 +941,7 @@ The example below define a database named |ques|.
}
\end{verbatim}
-\begin{function}{\dbshow}
+\begin{function}[added=2022-01-05]{\dbshow}
\begin{syntax}
\cs{dbshow} \marg{style} \marg{database}
\end{syntax}
@@ -744,36 +949,45 @@ The example below define a database named |ques|.
Show the \meta{database} with \meta{style}.
\end{function}
-\begin{function}{\dbclear}
+\changes{1.2}{2022-01-07}{Add macro}{\cs{dbclear}}
+\begin{function}[added=2022-01-07]{\dbclear}
\begin{syntax}
\cs{dbclear} \marg{database}
\end{syntax}
Clear the content of \meta{database}.
-
\end{function}
\subsection{\cs{dbNewStyle} and Style Options}
-\begin{function}{\dbNewStyle}
+\begin{function}[added=2022-01-05]{\dbNewStyle}
\begin{syntax}
\cs{dbNewStyle} \oarg{base styles} \marg{style} \marg{database} \marg{opts}
\end{syntax}
-Define a new \meta{style} that binds to \meta{database}. The style can inherit
-from a list of \meta{base styles} such as
-|\dbNewStyle[base1, base2]{new-style}{ques}{}|.
+ Define a new \meta{style} that binds to \meta{database}. The style can
+ inherit from a list of \meta{base styles} such as
+ |\dbNewStyle[base1, base2]{new-style}{ques}{}|.
\end{function}
\subsubsection{General Options}
-\begin{option}{opt=filter, desc={= \meta{filter}}, init=-none-}
+\begin{option}[added=2022-01-05]{filter}
+ \begin{syntax}
+ filter = <filter>
+ \end{syntax}
+
Set the \meta{filter} defined by \cs{dbCombineFilters}.
\end{option}
-\begin{option}{opt=raw-filter, desc={= \meta{cond combination}}}
- Set anonymous with defined conditionals. Two examples below perform the same
- function.
+\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>
+ \end{syntax}
+
+ Set anonymous with conditionals defined by \cs{dbNewConditional}. Two
+ filters shows in the code below have the same meaning.
\end{option}
\begin{verbatim}
@@ -792,10 +1006,12 @@ from a list of \meta{base styles} such as
\dbNewStyle{style}{db}{filter=filter}
\end{verbatim}
-\begin{option}{
- opt = sort,
- desc = {= \{ \meta{attr spec1}, \meta{attr spec2}, \ldots{} \}},
-}
+\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{} \}
+ \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
@@ -816,31 +1032,40 @@ from a list of \meta{base styles} such as
}
\end{verbatim}
-\begin{option}{
- opt = item-code,
- desc = {= \meta{item code}}
-}
+\begin{option}[added=2022-01-05, rEXP]{item-code}
+ \begin{syntax}
+ item-code = <code>
+ \end{syntax}
+
Set the code that show a single record. You can use \cs{dbuse} to display
certian attribute.
\end{option}
-\begin{option}{
- opt = {\meta{attr}/sep},
- desc = {= \meta{sep spec}},
- init = {,~\~}
-}
-\begin{Syntax}
- \meta{attr}/separator = \meta{separator} \\
- \meta{attr}/separator = \{ \\
- ~~\meta{separator between two}, \\
- ~~\meta{separator between more than two}, \\
- ~~\meta{separator between final two} \\
- \}
-\end{Syntax}
-
- Only for attributes of type |clist|. Set the separator between clist items.
- The first form accept one arguments and set the seperator as \meta{sep}. The
- second form is more complicated, the following documentation is quoted from
+\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}
+ <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} \\
+ \} \\
+ \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
@@ -851,7 +1076,39 @@ from a list of \meta{base styles} such as
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}
+
+\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/zfill}}
+\begin{option}[added=2022-01-08, EXP]{<attr>/zfill}
+ \begin{syntax}
+ <attr>/zfill = <\TTF>
+ \end{syntax}
+ Only for attributes of type |date|. Control whether to fill zero on the left
+ of the month or day.
\end{option}
\subsubsection{Decorators}
@@ -889,69 +1146,89 @@ decorators.
}
\end{verbatim}
-\begin{option}{
- opt = before-code,
- desc = {= \meta{before code}}
-}
- Set the \meta{before code} that is executed before displaying the database.
+\changes{1.3}{2022-01-08}{Add option}{\opt{<attr>/wrapper}}
+\begin{option}[added=2022-01-08, rEXP]{<attr>/wrapper}
+ \begin{syntax}
+ <attr>/wrapper = <control sequence>
+ \end{syntax}
+
+ Only for attributes of type |date|. Output of \cs{dbuse}\marg{date attr}
+ will be \meta{control sequence}\marg{date}.
\end{option}
-\begin{option}{
- opt = after-code,
- desc = {= \meta{after code}}
-}
- Set the \meta{after code} that is executed after displaying the database.
+\begin{option}[added=2022-01-05, rEXP]{before-code}
+ \begin{syntax}
+ before-code = <code>
+ \end{syntax}
+
+ Set the \meta{code} that is executed \enbefore displaying the database.
\end{option}
-\begin{option}{
- opt = record-before-code,
- desc = {= \meta{before code}}
-}
- Set the \meta{before code} that is executed before displaying the record.
+\begin{option}[added=2022-01-05, rEXP]{after-code}
+ \begin{syntax}
+ after-code = <code>
+ \end{syntax}
+
+ Set the \meta{code} that is executed \enafter displaying the database.
\end{option}
-\begin{option}{
- opt = record-after-code,
- desc = {= \meta{after code}}
-}
- Set the \meta{after code} that is executed after displaying the record.
+\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}
+ \begin{syntax}
+ record-before-code = <code>
+ \end{syntax}
+
+ Set the \meta{code} that is executed \enbefore displaying a record.
\end{option}
-\begin{option}{
- opt = {\meta{attr}/before-code},
- desc = {= \meta{before code}}
-}
- Set the \meta{before code} that is executed by \cs{dbuse} before displaying
+\begin{option}[added=2022-01-05, rEXP]{record-after-code}
+ \begin{syntax}
+ record-after-code = <code>
+ \end{syntax}
+
+ Set the \meta{code} that is executed \enafter displaying the record.
+\end{option}
+
+\begin{option}[added=2022-01-05, rEXP]{<attr>/before-code}
+ \begin{syntax}
+ <attr>/before-code = <code>
+ \end{syntax}
+
+ Set the \meta{code} that is executed by \cs{dbuse} \enbefore displaying
certain attribute.
\end{option}
-\begin{option}{
- opt = {\meta{attr}/after-code},
- desc = {= \meta{after code}}
-}
- Set the \meta{after code} that is executed by \cs{dbuse} after displaying
+\begin{option}[added=2022-01-05, rEXP]{<attr>/after-code}
+ \begin{syntax}
+ <attr>/after-code = <code>
+ \end{syntax}
+
+ Set the \meta{code} that is executed by \cs{dbuse} \enafter displaying
certain attribute.
\end{option}
-\begin{option}{
- opt = {\meta{attr}/item-before-code},
- desc = {= \meta{before code}}
-}
- Only for attributes of type |clist|. Set the \meta{after code} that is
- excuted before displaying the item of the comma list.
+\begin{option}[added=2022-01-05, rEXP]{<attr>/item-before-code}
+ \begin{syntax}
+ <attr>/item-before-code = <code>
+ \end{syntax}
+
+ Only for attributes of type |clist|. Set the \meta{code} that is excuted
+ \enbefore displaying the item of the comma list.
\end{option}
-\begin{option}{
- opt = {\meta{attr}/item-after-code},
- desc = {= \meta{after code}}
-}
- Only for attributes of type |clist|. Set the \meta{after code} that is
- excuted after displaying the item of the comma list.
+\begin{option}[added=2022-01-05, rEXP]{<attr>/item-after-code}
+ \begin{syntax}
+ <attr>/item-after-code = <code>
+ \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}
-\begin{function}{\dbNewReviewPoints}
+\begin{function}[added=2022-01-05]{\dbNewReviewPoints}
\begin{syntax}
\cs{dbNewReviewPoints} \marg{name} \marg{points}
\end{syntax}
@@ -960,6 +1237,8 @@ decorators.
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.
+\end{function}
+
\begin{verbatim}
\dbNewReviewPoints{review-point}{2, 5, 15} % define points
\begin{dbFilters}
@@ -968,71 +1247,78 @@ decorators.
\end{dbFilters}
\dbNewStyle{review-style}{ques}{filter=filter1} % define style
\end{verbatim}
-\end{function}
\subsection{Define Filters inside \env{dbFilters} Environment}
-\noindent\DescribeEnv{dbFilters}
-\begin{Syntax}*
- |\begin{dbFilters}|\marg{database} \\
- ~~\meta{code}
- |\end{dbFilters}| \\
-\end{Syntax}
+\begin{environment}[added=2022-01-05]{dbFilters}
+ \begin{syntax}
+ |\begin{dbFilters}|\marg{database} \\
+ ~~\meta{code}
+ |\end{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.
+ 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.
+\end{environment}
-\begin{function}{\dbNewConditional, \dbNewConditional*}
+\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbNewConditional, \dbNewConditional*}
\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{relation} \\
- \cs{dbNewConditional}* \marg{name} \marg{int/fp attr} \marg{relation} \\
+ \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} \{\meta{review points}\textbar\meta{date}\} \\
- \cs{dbNewConditional}* \marg{name} \marg{date attr} \marg{relation}
+ \cs{dbNewConditional} \marg{name} \marg{date attr} \marg{expr}
+ \cs{dbNewConditional}* \marg{name} \marg{date attr} \{\meta{review points}\orbar\meta{date}\} \\
\end{syntax}
Define the conditional named \meta{name} that binds to \meta{attr}. \cs{dbval}
is replaced with the real value of the attribute inside the \meta{cond spec}.
\end{function}
-For attributes of type |int| and |fp|, two forms have the same definition.
-\meta{relation} can be a single relation formula, such as |\dbval > 3|, or the
-combination of several relation formulas, such as |\dbval > 3 && \dbval < 10.2|.
-Supported operators are |<, >, =, ==, !=, >=, <=, !|.
+ \changes{1.3}{2022-01-10}{Update doc}{truncated division}
+ For attributes of type |int| and |fp|, \meta{expr} is passed to
+ \cs{int_compare:nTF} or \cs{fp_compare:nTF}.
+ \begin{note}
+ Division using |/| rounds to the closest integer. Use \cs{dbIntDivTruncate} to rounds
+ the result toward 0.
+ \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}.
-For attribute of type |str| and |tl|, unstarred form matches any part while
-starred form matches the whole part with the \meta{regex expr}.
\begin{verbatim}
- \dbNewConditional{cond1}{str-attr}{abc} % match abc, abcd, 1abc, =abc=, etc
+ \dbNewConditional {cond1}{str-attr}{abc} % match abc, abcd, 1abc, =abc=, etc
\dbNewConditional*{cond2}{str-attr}{abc} % only match abc
\end{verbatim}
-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.
+ 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.
\begin{verbatim}
- \dbNewConditional{cond1}{clist-attr}{a, b, c} % {a, b, d} -> true
+ \dbNewConditional {cond1}{clist-attr}{a, b, c} % {a, b, d} -> true
\dbNewConditional*{cond2}{clist-attr}{a, b, c} % {a, b, d} -> false
\end{verbatim}
-For attributes of type |date|, unstarred form uses \meta{review points} to
-define the conditional and \meta{date} is the date to be compared. The starred
-form define the conditional with \textbf{single} relation formula. Supported
-operators are |<, >, =, ==, !=, >=, <=|.
+ \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}.
+ Starred form defines the conditional with review points defined by
+ \cs{dbNewRdbNewReviewPoints} and \meta{date} is the date to be compared.
-\begin{function}{\dbCombineConditionals}
+\begin{function}[added=2022-01-05]{\dbCombineConditionals}
\begin{syntax}
\cs{dbCombineConditionals} \marg{name} \marg{cond combination} \oarg{info}
\end{syntax}
@@ -1046,43 +1332,49 @@ operators are |<, >, =, ==, !=, >=, <=|.
\subsection{Store Data with \env{dbitem} Environment}
-\noindent\DescribeEnv{dbitem}
-\begin{Syntax}*
- |\begin{dbitem}|\marg{database}[ \\
- ~~\meta{attr1} = \meta{val1}, \\
- ~~\meta{attr2} = \meta{val2}, \\
- ~~\ldots{} \\
- ] \\
- ~~\meta{code} \\
- |\end{dbitem}|
-\end{Syntax}
-
-The data are stored with \env{dbitem} environment in two ways. Smaller data
-can be stored in the option list and the bigger data can be stored by
-\cs{dbsave}, which will suppress the value set by the option list. An example
-code is showned below.
+\begin{environment}[added=2022-01-05]{dbitem}
+ \begin{syntax}
+ |\begin{dbitem}|\marg{database}[ \\
+ ~~\meta{attr1} = \meta{val1}, \\
+ ~~\meta{attr2} = \meta{val2}, \\
+ ~~\ldots{} \\
+ ] \\
+ ~~\meta{code} \\
+ |\end{dbitem}|
+ \end{syntax}
+
+ The data are stored with \env{dbitem} environment in two ways. Smaller data
+ can be stored in the option list and the bigger data can be stored by
+ \cs{dbsave}, which will suppress the value set by the option list. An
+ example code is showned below.
+\end{environment}
\begin{verbatim}
\begin{dbitem}[date=2022-01-01, info=test]
\dbsave{question}{This is a test question.}
- \dbsave{answer}{This is the correct answer of the question.}
+ \dbsave{answer} {This is a test answer.}
\end{dbitem}
\end{verbatim}
\subsection{\cs{dbsave} and \cs{dbuse}}
-\begin{function}{\dbsave}
+\changes{1.3}{2022-01-08}{Add macro}{\cs{dbsave*}}
+\begin{function}[added=2022-01-05, updated=2022-01-08]{\dbsave, \dbsave*}
\begin{syntax}
- \cs{dbsave} \marg{attr} \marg{data}
+ \cs{dbsave} \marg{attr} \marg{data} \\
+ \cs{dbsave}* \marg{attr} \marg{data}
\end{syntax}
\cs{dbsave} save the \meta{data} to \meta{attr} of current record.
\cs{dbsave} can be used only inside the \env{dbitem} environment.
+ \meta{data} stored by \cs{dbsave*} is wrapped with \cs{exp_not:n} while
+ \meta{data} stored by \cs{dbsave} keeps the same.
\end{function}
-\begin{function}[EXP]{\dbuse}
+\changes{1.2}{2022-01-08}{Update macro}{make \cs{dbuse} fully-expandable}
+\begin{function}[added=2022-01-05, updated=2022-01-08, EXP]{\dbuse}
\begin{syntax}
- \cs{dbuse} \marg{attr}
+ \cs{dbuse} \marg{attr}
\end{syntax}
Display the value of \meta{attr} of current record. \cs{dbuse} is
@@ -1091,7 +1383,7 @@ code is showned below.
\subsection{Conditionals}
-\begin{function}[EXP]{\dbIfEmptyT, \dbIfEmptyF, \dbIfEmptyTF}
+\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} \\
@@ -1110,43 +1402,77 @@ code is showned below.
}
\end{verbatim}
-\subsection{Special Macros}
-
-Some special macros are defined to expand to different contents according to context.
-
-\DescribeMacro{\dbval} Attribute value, only accessible in \cs{dbNewConditional}.
-
-\DescribeMacro{\dbDatabase} Database name.
-
-\DescribeMacro{\dbFilterName} Filter name.
+\changes{1.2}{2022-01-08}{Remove macros}{\cs{dbItemIfEmpty(TF)}, \cs{dbClistItemIfEmpty(TF)}}
-\DescribeMacro{\dbFilterInfo} Filter information.
+\subsection{Expression Functions}
-\DescribeMacro{\dbIndex} Index of original records, which is equal to |\rvuse{id}| but \cs{rvuse} is nonexpandable.
-
-
-\DescribeMacro{\dbarabic} Show the counter of query set as digits.
-
-\DescribeMacro{\dbalph} Show the counter of query set as lowercase letters.
+\changes{1.3}{2022-01-10}{Add macros}{expression function aliases}
+\begin{function}[added=2022-01-10, EXP]{
+ \dbIntAbs, \dbIntSign, \dbIntDivRound, \dbIntDivTruncate, \dbIntMax,
+ \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} \\
+\end{function}
-\DescribeMacro{\dbAlph} Show the counter of query set as uppercase letters.
+\subsection{Special Macros}
-\DescribeMacro{\dbroman} Show the counter of query set as roman numerals.
+Some special macros are defined to expand to different contents according to context.
-\DescribeMacro{\dbRoman} Show the counter of query set as Roman numerals.
+\changes{1.1}{2022-01-05}{Add macro}{
+ \cs{dbarabic}, \cs{dbalph}, \cs{dbAlph}, \cs{dbroman},
+ \cs{dbRoman}
+}
+\changes{1.1}{2022-01-06}{Fix bug}{\cs{dbIndex} not defined}
+\begin{function}[added=2022-01-05, EXP]{
+ \dbval, \dbDatabase, \dbFilterName, \dbFilterInfo,
+ \dbIndex, \dbarabic, \dbalph, \dbAlph, \dbroman, \dbRoman
+}
+\begin{tblr}{ll}
+ \cs{dbval} & Attribute value, only according in \cs{dbNewConditional}. \\
+ \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}
+\end{function}
\section{Example of Flaw Sweeper Template}
\label{sec:example}
+\changes{1.1}{2022-01-07}{Update doc}{improve example}
+
\begin{tcblisting}{enhanced jigsaw,lower separated=false,
-leftlower=0pt,rightlower=0pt,
-colframe=red!50!black,colback=yellow!10!white,
-listing options={style=tcblatex,texcsstyle=*\color{red!70!black}},
-listing and comment,
-pdf comment,freeze pdf,
-compilable listing,
-breakable,
-run pdflatex
+ leftlower=0pt,rightlower=0pt,
+ colframe=red!50!black,colback=yellow!10!white,
+ listing options={style=tcblatex,texcsstyle=*\color{red!70!black}},
+ listing and comment,
+ pdf comment,freeze pdf,
+ compilable listing,
+ breakable,
+ run pdflatex
}
\documentclass{article}
\usepackage{amsmath, physics}
@@ -1202,7 +1528,8 @@ run pdflatex
\begin{dbFilters}{ques-book}
\dbNewConditional{hard}{labels}{hard}
\dbNewConditional{bad}{count}{\dbval > 1}
- \dbNewConditional{review}{date}{review|2022-01-07}
+ \dbNewConditional*{review}{date}{review|2022/01/07}
+ \dbNewConditional{after}{date}{\dbval > 2022/01/02}
\end{dbFilters}
% show all questions with hyperlink to answers
@@ -1260,23 +1587,29 @@ run pdflatex
labels/sep = /,
}
-% show all hard questions that have answered incorrectly for more than one
-% time with hyperlink to answers
+% 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
+% 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}
}
@@ -1284,7 +1617,7 @@ run pdflatex
\begin{document}
\begin{dbitem}{ques-book}[
- date=2022-01-01,
+ date=2022/01/01,
labels={math, equation, easy},
count=2
]
@@ -1297,7 +1630,7 @@ run pdflatex
\end{dbitem}
\begin{dbitem}{ques-book}[
- date=2022-01-01,
+ date=2022/01/01,
labels={math, equation, hard},
count=3
]
@@ -1310,7 +1643,7 @@ run pdflatex
\end{dbitem}
\begin{dbitem}{ques-book}[
- date=2022-01-04,
+ date=2022/01/04,
labels={math, integral, hard},
count=1
]
@@ -1325,35 +1658,5 @@ run pdflatex
\end{document}
\end{tcblisting}
-\section*{Change History}
-\markboth{Change History}{Change History}
-\addcontentsline{toc}{section}{Change History}
-\noindent
-\begin{tblr}{
- colspec = {lll},
- row{1} = {font=\bfseries},
-}
- Date & Ver. & Describe \\
- 2022-01-05 & 1.0 & {
- First version \\
- Add macro: \cmd{\dbarabic}, \cmd{\dbalph}, \cmd{\dbAlph}, \cmd{\dbroman}, \cmd{\dbRoman}
- } \\
- 2022-01-06 & & {
- Fix bug: \cmd{\dbIndex} undefined \\
- Add style option: \opt{raw-filter}
- } \\
- 2022-01-07 & 1.1 & Improve example \\
- 2022-01-07 & 1.1.1 & Add macro: \cmd{\dbclear} \\
- 2022-01-07 & 1.1.2 & Add documentation: comparison to \pkg{datatool} \\
- 2022-01-08 & 1.2 & {
- Fix str sorting bug \\
- Remove macros: \cmd{\dbItemIfEmpty(TF)}, \cmd{\dbClistItemIfEmpty(TF)} \\
- Make \cs{dbuse} expandable \\
- Add option: \opt{record-before-code}, \opt{record-after-code}
- } \\
-\end{tblr}
-
\end{documentation}
-
-
\end{document}
diff --git a/macros/latex/contrib/dbshow/dbshow.sty b/macros/latex/contrib/dbshow/dbshow.sty
index 68ac7b1d35..d60c993db1 100644
--- a/macros/latex/contrib/dbshow/dbshow.sty
+++ b/macros/latex/contrib/dbshow/dbshow.sty
@@ -14,18 +14,15 @@
% The Current Maintainer of this work is Li Changkai.
%
% This work consists of the files dbshow.sty, dbshow-doc.tex.
-\def\myfileversion{v1.2}
-\def\myfiledate{2022/01/08}
+\def\myfileversion{v1.3}
+\def\myfiledate{2022/01/10}
\RequirePackage{expl3, xparse}
-\RequirePackage[calc]{datetime2}
\ProvidesExplPackage
{dbshow}
{\myfiledate}
{\myfileversion}
{database to store and show data}
-\DTMsetdatestyle{iso}
-
\msg_new:nnn { dbshow } { non-existent-database } {
Database~'#1'~does~not~exist~\msg_line_context:.
}
@@ -91,44 +88,31 @@
{ \msg_fatal:nnn { dbshow } { non-existent-type } { #1 } }
}
-% #1 count #2 content
+% #1 valid count #2 real count #3 content
\msg_new:nnn { dbshow } { wrong-seperator } {
- option~sep~should~contain~1~or~3~items~but~only~#1~items~was~given,~
- sep~=~\{#2\}~\msg_line_context:.
+ option~'sep'~should~contain~#1~items~but~only~#2~items~was~given,~
+ sep~=~\{#3\}~\msg_line_context:.
}
-\cs_new:Nn \dbshow_sep_error:nn {
- \msg_error:nnnn { dbshow } { wrong-seperator } { #1 } { #2 }
+% #1 valid count #2 real count #3 content
+\cs_new:Nn \dbshow_sep_error:nnn {
+ \msg_error:nnnnn { dbshow } { wrong-seperator } { #1 } { #2 } { #3 }
}
-\cs_generate_variant:Nn \dbshow_sep_error:nn { xx }
+\cs_generate_variant:Nn \dbshow_sep_error:nnn { xxx }
\msg_new:nnn { dbshow } { unsupported-sort-type } {
unsupported~sort~type:~'#1'~\msg_line_context:.~The~type~should~be~one~of~
\{str,~date,~int,~fp\}.
}
-\clist_const:Nn \dbshow_type_clist { date, str, tl, clist, int, fp }
-
-\prop_const_from_keyval:Nn \dbshow_new_cs_map {
- date = str_clear_new:c,
- str = str_clear_new:c,
- tl = tl_gclear_new:c,
- clist = clist_gclear_new:c,
- int = int_gzero_new:c,
- fp = fp_gzero_new:c
+\msg_new:nnn { dbshow } { invalid-relation } {
+ invalid~relation:~'#1'.
}
-\prop_const_from_keyval:Nn \dbshow_set_cs_map {
- date = str_gset:cn,
- str = str_gset:cn,
- tl = tl_gset:cn,
- clist = clist_gset:cn,
- int = int_gset:cn,
- fp = fp_gset:cn
-}
+\clist_const:Nn \dbshow_type_clist { date, str, tl, clist, int, fp }
\prop_const_from_keyval:Nn \dbshow_default_value {
- date = \Today,
+ date = \dbtoday,
str = ,
tl = ,
clist = ,
@@ -136,15 +120,16 @@
fp = 0
}
-\newcount\l_dbshow_date_diff
-\clist_new:N \l_style_sep_clist
-\tl_new:N \l_style_item_before_code
-\tl_new:N \l_style_item_after_code
\cs_generate_variant:Nn \clist_use:nn { xx }
\cs_generate_variant:Nn \clist_use:nnnn { xxxx }
+\cs_generate_variant:Nn \prop_get:NnN { cVN }
+\cs_generate_variant:Nn \regex_extract_all:nnN { nVN }
+\cs_generate_variant:Nn \regex_split:nnN { nVN }
\prg_generate_conditional_variant:Nnn \str_compare:nNn { VNV } { TF }
\prg_generate_conditional_variant:Nnn \int_compare:nNn { VNV } { TF }
\prg_generate_conditional_variant:Nnn \fp_compare:nNn { VNV } { TF }
+\prg_generate_conditional_variant:Nnn \regex_match:nn { VV } { TF }
+\prg_generate_conditional_variant:Nnn \clist_if_in:Nn { Nx } { TF }
% #1 database #2 attr #3 type #4 default value
\cs_new:Npn \dbshow_process_default_value:w #1|#2=#3|#4\scan_stop {
@@ -214,20 +199,29 @@
% #1 database #2 attr #3 content
\cs_new:Nn \dbshow_save_data:nnn {
\dbshow_check_attr:nn { #1 } { #2 }
- \str_set:Nx \l_tmp_type { \dbshow_get_type:nn { #1 } { #2 } }
- \prop_get:NVN \dbshow_new_cs_map \l_tmp_type \l_tmp_cs_new
- \prop_get:NVN \dbshow_set_cs_map \l_tmp_type \l_tmp_cs_set
- \use:c { \l_tmp_cs_new }
- { g__dbshow_data_#1_#2_\dbshow_get_counter:n { #1 } }
- \use:c { \l_tmp_cs_set }
- { g__dbshow_data_#1_#2_\dbshow_get_counter:n { #1 } } { #3 }
+ \use:c {
+ \str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#1 } { #2 } } {
+ { str } { str_clear_new:c }
+ { tl } { tl_gclear_new:c }
+ { clist } { clist_gclear_new:c }
+ { int } { int_gzero_new:c }
+ { fp } { fp_gzero_new:c }
+ { date } { dbshow_date_gclear_new:n }
+ }
+ } { g__dbshow_data_#1_#2_\int_use:c { g__dbshow_counter_#1 } }
+ \use:c {
+ \str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#1 } { #2 } } {
+ { str } { str_gset:cn }
+ { tl } { tl_gset:cn }
+ { clist } { clist_gset:cn }
+ { int } { int_gset:cn }
+ { fp } { fp_gset:cn }
+ { date } { dbshow_date_gset:nx }
+ }
+ } { g__dbshow_data_#1_#2_\int_use:c { g__dbshow_counter_#1 } } { #3 }
}
\cs_generate_variant:Nn \dbshow_save_data:nnn { nnx }
-\cs_new:Nn \dbshow_brace:n {
- \exp_not:n { { #1 } }
-}
-
% #1 before code tl #2 after code tl #3 item
\cs_new:Nn \dbshow_clist_wrapper:NNn {
\exp_not:n { { #1#3#2 }, }
@@ -249,26 +243,63 @@
{ \clist_item:Nn #2 { 3 } }
}
} {
- \dbshow_sep_error:xx
+ \dbshow_sep_error:xxx
+ { 1~or~3 }
{ \clist_count:N #2 }
- { \clist_use:Nn #2 { , } }
+ { \clist_use:Nn #2 { ,~ } }
}
}
\cs_generate_variant:Nn \dbshow_clist_use:NNNN { cccc }
+% #1 date #2 sep #3 zfill bool
+\cs_new:Nn \dbshow_date_use:nNN {
+ \int_case:nnF { \clist_count:N #2 } {
+ { 1 } {
+ \bool_if:NTF { #3 }
+ { \dbshow_date_use_zfill:nf }
+ { \dbshow_date_use:nf }
+ { #1 }
+ { \clist_item:Nn #2 { 1 } }
+ }
+ { 4 } {
+ \bool_if:NTF { #3 }
+ { \dbshow_date_use_zfill:nffff }
+ { \dbshow_date_use:nffff }
+ { #1 }
+ { \clist_item:Nn #2 { 1 } }
+ { \clist_item:Nn #2 { 2 } }
+ { \clist_item:Nn #2 { 3 } }
+ { \clist_item:Nn #2 { 4 } }
+ }
+ } {
+ \dbshow_sep_error:xxx
+ { 1~or~4 }
+ { \clist_count:N #2 }
+ { \clist_use:Nn #2 { ,~ } }
+ }
+}
+\cs_generate_variant:Nn \dbshow_date_use:nNN { ncc }
+
% #1 database #2 attr #3 index #4 style
\cs_new:Nn \dbshow_use_data:nnnn {
\str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#1 } { #2 } } {
- { date } { \str_use:c { g__dbshow_data_#1_#2_#3 } }
{ str } { \str_use:c { g__dbshow_data_#1_#2_#3 } }
{ tl } { \tl_use:c { g__dbshow_data_#1_#2_#3 } }
{ int } { \int_use:c { g__dbshow_data_#1_#2_#3 } }
{ fp } { \fp_use:c { g__dbshow_data_#1_#2_#3 } }
{ clist } {
\dbshow_clist_use:cccc { g__dbshow_data_#1_#2_#3 }
- { g__dbshow_style_clist_sep_#4_#1_#2 }
- { g__dbshow_style_clist_item_before_#4_#1_#2 }
- { g__dbshow_style_clist_item_after_#4_#1_#2 }
+ { g__dbshow_style_attr_sep_#4_#1_#2 }
+ { g__dbshow_style_attr_item_before_#4_#1_#2 }
+ { g__dbshow_style_attr_item_after_#4_#1_#2 }
+ }
+ { date } {
+ \exp_args:Nnx
+ \tl_use:c { g__dbshow_style_attr_wrapper_#4_#1_#2 } {
+ \dbshow_date_use:ncc { g__dbshow_data_#1_#2_#3 }
+ { g__dbshow_style_attr_sep_#4_#1_#2 }
+ { g__dbshow_style_attr_zfill_#4_#1_#2 }
+ }
}
}
}
@@ -307,9 +338,13 @@
\prop_map_function:cN { g__dbshow_type_map_#1 } \dbshow_set_default:nn
\dbshow_save_data:nnx { #1 } { id } { \dbshow_get_counter:n { #1 } }
\keys_set:nn { dbshow/database/#1 } { #2 }
- % #2 attr #3 content
- \NewDocumentCommand { \dbsave } { m m } {
- \dbshow_save_data:nnn { #1 } { ##1 } { ##2 }
+ % ##1 exp or not ##2 attr ##3 content
+ \NewDocumentCommand { \dbsave } { s m m } {
+ \IfBooleanTF { ##1 } {
+ \dbshow_save_data:nnn { #1 } { ##2 } { \exp_not:n { ##3 } }
+ } {
+ \dbshow_save_data:nnn { #1 } { ##2 } { ##3 }
+ }
}
} { #3 }
@@ -368,43 +403,53 @@
\tl_set:Nn \l_date_tl { #2 }
}
-\cs_new:Nn \dbshow_if_date: {
- \bool_if:NTF \l_star_bool {
- \regex_extract_once:nVNF { \A(.*)([!<>=]+)(.*)\Z }
- \l_dbshow_rela \l_tmpa_seq { }
- \exp_args:Nnx \DTMsavedate{day1}{ \seq_item:Nn \l_tmpa_seq { 2 } }
- \tl_set:Nx \l_rela { \seq_item:Nn \l_tmpa_seq { 3 } }
- \exp_args:Nnx \DTMsavedate{day2}{ \seq_item:Nn \l_tmpa_seq { 4 } }
- \DTMsaveddatediff{day1}{day2}{\l_dbshow_date_diff}% specious blank
- \exp_args:NnV \int_compare:nNnTF
- { \the\l_dbshow_date_diff } \l_rela { 0 }
+\cs_new_protected:Nn \dbshow_if_date: {
+ \int_zero_new:N \l__dbshow_if_tmpa_int
+ \int_zero_new:N \l__dbshow_if_tmpb_int
+ \int_zero_new:N \l__dbshow_if_diff_int
+ \bool_if:NTF \l_star_bool { % review points
+ \exp_after:wN \dbshow_parse_date:w \l_dbshow_rela\dbshow_stop
+ \dbshow_date_clear_new:n { tmp_day1 }
+ \dbshow_date_clear_new:n { tmp_day2 }
+ \dbshow_date_set:nx { tmp_day1 } { \l_date_tl }
+ \dbshow_date_set:nx { tmp_day2 } { \dbval }
+ \dbshow_date_sub:nnN { tmp_day1 } { tmp_day2 } \l__dbshow_if_diff_int
+ \clist_if_in:NxTF \l_point_clist { \int_use:N \l__dbshow_if_diff_int }
{ \dbshow_set_true: }
{ \dbshow_set_false: }
}
- {
- \exp_after:wN \dbshow_parse_date:w \l_dbshow_rela\dbshow_stop
- \exp_args:Nnx \DTMsavedate{day1}{ \l_date_tl }
- \exp_args:Nnx \DTMsavedate{day2}{ \dbval }
- \DTMsaveddatediff{day1}{day2}{\l_dbshow_date_diff}% specious blank
- \clist_if_in:NoTF \l_point_clist { \the\l_dbshow_date_diff }
+ { % rela
+ \tl_set:Nx \l_dbshow_rela { \l_dbshow_rela }
+ \regex_extract_all:nVN { \d{4}/\d+/\d+ } \l_dbshow_rela \l_date_seq
+ \regex_split:nVN { \d{4}/\d+/\d+ } \l_dbshow_rela \l_other_seq
+ \tl_clear:N \l_dbshow_rela
+ \int_set:Nn \l__dbshow_if_tmpa_int { \seq_count:N \l_date_seq }
+ \int_step_inline:nn { \l__dbshow_if_tmpa_int } {
+ \tl_put_right:Nx \l_dbshow_rela { \seq_item:Nn \l_other_seq { ##1 } }
+ \dbshow_date_clear_new:n { rela-tmp }
+ \dbshow_date_set:nx { rela-tmp } { \seq_item:Nn \l_date_seq { ##1 } }
+ \dbshow_date_to_int:nN { rela-tmp } \l__dbshow_if_tmpb_int
+ \tl_put_right:Nx \l_dbshow_rela { \int_use:N \l__dbshow_if_tmpb_int }
+ }
+ \tl_put_right:Nx \l_dbshow_rela {
+ \seq_item:Nn \l_other_seq { \l__dbshow_if_tmpa_int + 1 }
+ }
+ \int_compare:nTF { \l_dbshow_rela }
{ \dbshow_set_true: }
{ \dbshow_set_false: }
}
}
-\cs_generate_variant:Nn \prop_get:NnN { cVN }
-\prg_generate_conditional_variant:Nnn \regex_extract_once:nnN { nVN } { T, F, TF, p }
-\prg_generate_conditional_variant:Nnn \regex_match:nn { VV } { T, F, TF, p }
% #1 database name #2 cond name #3 index
\cs_set:Nn \dbshow_if:nnn {
\tl_set_eq:Nc \l_dbshow_attr { g__dbshow_filter_attr_#1_#2 }
\tl_set_eq:Nc \l_dbshow_rela { g__dbshow_filter_rela_#1_#2 }
+ \prop_get:cVN { g__dbshow_type_map_#1 } \l_dbshow_attr \l_tmp_type
\cs_set_eq:Nc \dbval { g__dbshow_data_#1_\l_dbshow_attr _#3 }
\cs_set:Nn \dbshow_set_true:
{ \bool_gset_true:c { g__dbshow_filter_bool_#1_#2 } }
\cs_set:Nn \dbshow_set_false:
{ \bool_gset_false:c { g__dbshow_filter_bool_#1_#2 } }
- \prop_get:cVN { g__dbshow_type_map_#1 } \l_dbshow_attr \l_tmp_type
\bool_set_eq:Nc \l_star_bool { g__dbshow_cond_star_#1_#2 }
\use:c { dbshow_if_\l_tmp_type : }
}
@@ -468,6 +513,8 @@
\clist_set:cn { g__review_points_#1 } { #2 }
}
+\cs_new:Nn \dbshow_identity:n { #1 }
+
% #1 style name #2 database name #3 attr
\cs_new_protected:Nn \dbshow_new_attr_style:nnn {
\dbshow_check_attr:nn { #2 } { #3 }
@@ -476,17 +523,23 @@
before-code .initial:n = ,
after-code .tl_gset:c = { g__dbshow_style_attr_after_#1_#2_#3 },
after-code .initial:n = ,
+ % for date and clist
+ sep .clist_gset:c = { g__dbshow_style_attr_sep_#1_#2_#3 },
+ % only for clist
+ item-before-code .tl_gset:c = { g__dbshow_style_attr_item_before_#1_#2_#3 },
+ item-before-code .initial:n = ,
+ item-after-code .tl_gset:c = { g__dbshow_style_attr_item_after_#1_#2_#3 },
+ item-after-code .initial:n = ,
+ % only for date
+ zfill .bool_gset:c = { g__dbshow_style_attr_zfill_#1_#2_#3 },
+ zfill .initial:n = true,
+ zfill .default:n = true,
+ wrapper .tl_gset:c = { g__dbshow_style_attr_wrapper_#1_#2_#3 },
+ wrapper .initial:n = { \dbshow_identity:n },
}
- \prop_get:cnN { g__dbshow_type_map_#2 } { #3 } \l_tmp_type
- \str_if_eq:eeT { \l_tmp_type } { clist } {
- \keys_define:nn { dbshow/style/#1/#3 } {
- sep .clist_gset:c = { g__dbshow_style_clist_sep_#1_#2_#3 },
- sep .initial:n = { { ,~ } },
- item-before-code .tl_gset:c = { g__dbshow_style_clist_item_before_#1_#2_#3 },
- item-before-code .initial:n = ,
- item-after-code .tl_gset:c = { g__dbshow_style_clist_item_after_#1_#2_#3 },
- item-after-code .initial:n = ,
- }
+ \str_case_e:nn { \prop_item:cn { g__dbshow_type_map_#2 } { #3 } } {
+ { clist } { \keys_set:nn { dbshow/style/#1/#3 } { sep = { { ,~ } } } }
+ { date } { \keys_set:nn { dbshow/style/#1/#3 } { sep = { { / } } } }
}
}
@@ -553,7 +606,7 @@
\int_zero:N \l_tmpa_int
\cs_set:Nn \dbshow_sort_single: {
\int_incr:N \l_tmpa_int
- \str_set:Nx \l_tmpa_str
+ \str_set:Nx \l_tmpa_str % attr
{ \clist_item:cn { g__dbshow_sort_#3_#1 } { \l_tmpa_int } }
\str_if_in:NnTF \l_tmpa_str { * } {
\exp_after:wN \dbshow_sort_parse_star:w \l_tmpa_str
@@ -564,15 +617,17 @@
}
\exp_args:NnV \dbshow_check_attr:nn { #1 } \l_tmpa_str
- \cs_set_eq:Nc \l_tmpa_tl { g__dbshow_data_#1_\l_tmpa_str _##1 }
- \cs_set_eq:Nc \l_tmpb_tl { g__dbshow_data_#1_\l_tmpa_str _##2 }
-
\prop_get:cVN { g__dbshow_type_map_#1 } \l_tmpa_str \l_tmp_type
\clist_if_in:nVF { str, int, date, fp } \l_tmp_type {
\msg_error:nnx { dbshow } { unsupported-sort-type } { \l_tmp_type }
}
- \str_if_eq:eeT { \l_tmp_type } { date }
- { \str_set:Nn \l_tmp_type { str } }
+
+ \str_if_eq:eeT { \l_tmp_type } { date } {
+ \str_set:Nn \l_tmp_type { str }
+ }
+
+ \cs_set_eq:Nc \l_tmpa_tl { g__dbshow_data_#1_\l_tmpa_str _##1 }
+ \cs_set_eq:Nc \l_tmpb_tl { g__dbshow_data_#1_\l_tmpa_str _##2 }
\cs_set_eq:Nc \dbshow_compare { \l_tmp_type _compare:VNVTF }
\dbshow_compare \l_tmpa_tl \l_op_same \l_tmpb_tl
@@ -660,4 +715,192 @@
{ #1 } { #2 } { g__dbshow_filter_#1_#2 }
}
+\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
+
+%%%%%%%%%%%%%%%%% date
+
+% #1 year
+\prg_new_conditional:Nnn \dbshow_date_if_leap:n { T, F, TF, p } {
+ \bool_if:nTF {
+ \int_compare_p:nNn { \int_mod:nn { #1 } { 400 } } = { 0 } ||
+ (
+ !\int_compare_p:nNn { \int_mod:nn { #1 } { 100 } } = { 0 } &&
+ \int_compare_p:nNn { \int_mod:nn { #1 } { 4 } } = { 0 }
+ )
+ }
+ { \prg_return_true: }
+ { \prg_return_false: }
+}
+
+\clist_const:Nn \dbshow_date_month_clist
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+
+\int_new:N \l__date_ans_int
+\int_new:N \l__date_tmpa_int
+\int_new:N \l__date_tmpb_int
+
+% #1 year #2 month #3 day #4 token to save the result
+\cs_new_protected:Nn \dbshow_date_to_int:nnnN {
+ \int_set:Nn \l__date_ans_int { #3 - 1 }
+ \int_step_inline:nn { #2 - 1 } {
+ \int_add:Nn \l__date_ans_int {
+ \clist_item:Nn \dbshow_date_month_clist { ##1 }
+ }
+ \bool_if:nT {
+ \int_compare_p:nNn { ##1 } = { 2 } &&
+ \dbshow_date_if_leap_p:n { #1 }
+ } { \int_incr:N \l__date_ans_int }
+ }
+ \int_add:Nn \l__date_ans_int { 365 * (#1 - 1971) }
+ \int_add:Nn \l__date_ans_int {
+ \int_div_truncate:nn { #1 - 1 } { 4 } -
+ \int_div_truncate:nn { 1971 } { 4 }
+ }
+ \int_sub:Nn \l__date_ans_int {
+ \int_div_truncate:nn { #1 - 1 } { 100 } -
+ \int_div_truncate:nn { 1971 } { 100 }
+ }
+ \int_add:Nn \l__date_ans_int {
+ \int_div_truncate:nn { #1 - 1 } { 400 } -
+ \int_div_truncate:nn { 1971 } { 400 }
+ }
+ \int_set_eq:NN #4 \l__date_ans_int
+}
+
+\cs_new_protected:Nn \dbshow_date_to_int:NNNN {
+ \dbshow_date_to_int:nnnN { #1 } { #2 } { #3 } #4
+}
+\cs_generate_variant:Nn \dbshow_date_to_int:NNNN { cccN }
+
+% #1 date #2 int
+\cs_new:Nn \dbshow_date_to_int:nN {
+ \dbshow_date_to_int:cccN
+ { dbshow_date_year_#1 }
+ { dbshow_date_month_#1 }
+ { dbshow_date_day_#1 }
+ #2
+}
+
+\cs_new_protected:Nn \dbshow_date_set_val:n {
+ \tl_set:cx { #1 } { \dbshow_date_use_zfill:nn { #1 } { / } }
+}
+\cs_new_protected:Nn \dbshow_date_gset_val:n {
+ \tl_gset:cx { #1 } { \dbshow_date_use_zfill:nn { #1 } { / } }
+}
+
+\cs_new_protected:Nn \dbshow_date_init:n {
+ \dbshow_date_set:nnnn { #1 } { 1971 } { 1 } { 1 }
+ \dbshow_date_set_val:n { #1 }
+}
+\cs_new_protected:Nn \dbshow_date_ginit:n {
+ \dbshow_date_gset:nnnn { #1 } { 1971 } { 1 } { 1 }
+ \dbshow_date_gset_val:n { #1 }
+}
+
+\cs_new_protected:Nn \dbshow_date_new:n {
+ \int_new:c { dbshow_date_year_#1 }
+ \int_new:c { dbshow_date_month_#1 }
+ \int_new:c { dbshow_date_day_#1 }
+ \dbshow_date_ginit:n { #1 }
+}
+
+\cs_new_protected:Nn \dbshow_date_clear_new:n {
+ \int_zero_new:c { dbshow_date_year_#1 }
+ \int_zero_new:c { dbshow_date_month_#1 }
+ \int_zero_new:c { dbshow_date_day_#1 }
+ \dbshow_date_init:n { #1 }
+}
+
+\cs_new_protected:Nn \dbshow_date_gclear_new:n {
+ \int_gzero_new:c { dbshow_date_year_#1 }
+ \int_gzero_new:c { dbshow_date_month_#1 }
+ \int_gzero_new:c { dbshow_date_day_#1 }
+ \dbshow_date_ginit:n { #1 }
+}
+
+% #1 name #2 year #3 month #4 day
+\cs_new_protected:Nn \dbshow_date_set:nnnn {
+ \int_set:cn { dbshow_date_year_#1 } { #2 }
+ \int_set:cn { dbshow_date_month_#1 } { #3 }
+ \int_set:cn { dbshow_date_day_#1 } { #4 }
+ \dbshow_date_set_val:n { #1 }
+}
+
+% #1 name #2 year #3 month #4 day
+\cs_new_protected:Nn \dbshow_date_gset:nnnn {
+ \int_gset:cn { dbshow_date_year_#1 } { #2 }
+ \int_gset:cn { dbshow_date_month_#1 } { #3 }
+ \int_gset:cn { dbshow_date_day_#1 } { #4 }
+ \dbshow_date_gset_val:n { #1 }
+}
+
+\cs_new_protected:Npn \dbshow_date_set:w #1\dbshow_sep#2/#3/#4\dbshow_stop {
+ \dbshow_date_clear_new:n { #1 }
+ \dbshow_date_set:nnnn { #1 } { #2 } { #3 } { #4 }
+}
+\cs_new_protected:Npn \dbshow_date_gset:w #1\dbshow_sep#2/#3/#4\dbshow_stop {
+ \dbshow_date_gclear_new:n { #1 }
+ \dbshow_date_gset:nnnn { #1 } { #2 } { #3 } { #4 }
+}
+
+% #1 date name #2 date
+\cs_new_protected:Nn \dbshow_date_set:nn {
+ \dbshow_date_set:w #1\dbshow_sep#2\dbshow_stop
+}
+\cs_generate_variant:Nn \dbshow_date_set:nn { nx }
+\cs_new_protected:Nn \dbshow_date_gset:nn {
+ \dbshow_date_gset:w #1\dbshow_sep#2\dbshow_stop
+}
+\cs_generate_variant:Nn \dbshow_date_gset:nn { nx }
+
+% #1 date 1 #2 date 2 #3 int token
+\cs_new_protected:Nn \dbshow_date_sub:nnN {
+ \dbshow_date_to_int:nN { #1 } \l__date_tmpa_int
+ \dbshow_date_to_int:nN { #2 } \l__date_tmpb_int
+ \int_set:Nn #3 { \l__date_tmpa_int - \l__date_tmpb_int }
+}
+
+\cs_new:Nn \dbshow_date_show_two:N {
+ \int_compare:nNnTF { #1 } > { 9 }
+ { \int_use:N #1 } { 0\int_use:N #1 }
+}
+\cs_generate_variant:Nn \dbshow_date_show_two:N { c }
+
+\cs_new:Nn \dbshow_date_use:nnnnn {
+ #2\int_use:c { dbshow_date_year_#1 }
+ #3\int_use:c { dbshow_date_month_#1 }
+ #4\int_use:c { dbshow_date_day_#1 }#5
+}
+\cs_generate_variant:Nn \dbshow_date_use:nnnnn { nffff }
+
+\cs_new:Nn \dbshow_date_use_zfill:nnnnn {
+ #2\int_use:c { dbshow_date_year_#1 }
+ #3\dbshow_date_show_two:c { dbshow_date_month_#1 }
+ #4\dbshow_date_show_two:c { dbshow_date_day_#1 }#5
+}
+\cs_generate_variant:Nn \dbshow_date_use_zfill:nnnnn { nffff }
+
+\cs_new:Nn \dbshow_date_use:nn {
+ \dbshow_date_use:nnnnn { #1 } { } { #2 } { #2 } { }
+}
+\cs_generate_variant:Nn \dbshow_date_use:nn { nf }
+
+\cs_new:Nn \dbshow_date_use_zfill:nn {
+ \dbshow_date_use_zfill:nnnnn { #1 } { } { #2 } { #2 } { }
+}
+\cs_generate_variant:Nn \dbshow_date_use_zfill:nn { nf }
+
+\tl_set:Nx \dbtoday {
+ \int_use:N \c_sys_year_int/
+ \int_use:N \c_sys_month_int/
+ \int_use:N \c_sys_day_int
+}
+
\endinput