From da0e202bdd0dc2f52f28ae0d96dc96969826890b Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Fri, 20 Aug 2021 03:01:54 +0000 Subject: CTAN sync 202108200301 --- macros/latex/contrib/animate/ChangeLog | 3 + macros/latex/contrib/animate/animate.pdf | Bin 3869206 -> 3878981 bytes macros/latex/contrib/animate/animate.sty | 10 +- macros/latex/contrib/animate/animate.tex | 24 +- macros/latex/contrib/easybook/easybook.dtx | 18 +- macros/latex/contrib/easybook/easybook.pdf | Bin 590797 -> 590649 bytes macros/latex/contrib/easybook/easybook.tex | 12 +- macros/latex/contrib/gamebooklib/Makefile | 20 + macros/latex/contrib/gamebooklib/README | 41 + macros/latex/contrib/gamebooklib/gamebooklib.dtx | 998 +++++++++++++++++++++ macros/latex/contrib/gamebooklib/gamebooklib.ins | 53 ++ macros/latex/contrib/gamebooklib/gamebooklib.pdf | Bin 0 -> 265430 bytes .../gamebooklib/gamebooklib_countpagesperseed.sh | 62 ++ .../latex/contrib/gamebooklib/gamebooklib_test.pdf | Bin 0 -> 117057 bytes .../latex/contrib/gamebooklib/gamebooklib_test.tex | 109 +++ macros/latex/contrib/lambdax/lambdax.bib | 26 + macros/latex/contrib/lambdax/lambdax.dtx | 19 +- macros/latex/contrib/lambdax/lambdax.pdf | Bin 0 -> 555406 bytes macros/latex/contrib/projlib/ProjLib-doc-cn.pdf | Bin 319814 -> 319918 bytes macros/latex/contrib/projlib/ProjLib-doc-en.pdf | Bin 199160 -> 199267 bytes macros/latex/contrib/projlib/ProjLib-doc-fr.pdf | Bin 200071 -> 200190 bytes macros/latex/contrib/projlib/ProjLib-doc.dtx | 6 +- macros/latex/contrib/projlib/ProjLib.dtx | 22 +- 23 files changed, 1371 insertions(+), 52 deletions(-) create mode 100644 macros/latex/contrib/gamebooklib/Makefile create mode 100644 macros/latex/contrib/gamebooklib/README create mode 100644 macros/latex/contrib/gamebooklib/gamebooklib.dtx create mode 100644 macros/latex/contrib/gamebooklib/gamebooklib.ins create mode 100644 macros/latex/contrib/gamebooklib/gamebooklib.pdf create mode 100755 macros/latex/contrib/gamebooklib/gamebooklib_countpagesperseed.sh create mode 100644 macros/latex/contrib/gamebooklib/gamebooklib_test.pdf create mode 100644 macros/latex/contrib/gamebooklib/gamebooklib_test.tex create mode 100644 macros/latex/contrib/lambdax/lambdax.bib create mode 100644 macros/latex/contrib/lambdax/lambdax.pdf (limited to 'macros/latex') diff --git a/macros/latex/contrib/animate/ChangeLog b/macros/latex/contrib/animate/ChangeLog index df96396f01..c7f679fd55 100644 --- a/macros/latex/contrib/animate/ChangeLog +++ b/macros/latex/contrib/animate/ChangeLog @@ -1,3 +1,6 @@ +2021-08-19 + * fix: wrong orientation of button faces on landscape pages (dvips) + 2021-06-11 * fix: `undefined references' warning, when placing animation in a \phantom diff --git a/macros/latex/contrib/animate/animate.pdf b/macros/latex/contrib/animate/animate.pdf index 1cb9d5a557..5a8488adc2 100644 Binary files a/macros/latex/contrib/animate/animate.pdf and b/macros/latex/contrib/animate/animate.pdf differ diff --git a/macros/latex/contrib/animate/animate.sty b/macros/latex/contrib/animate/animate.sty index a492a7677d..ed9681e490 100644 --- a/macros/latex/contrib/animate/animate.sty +++ b/macros/latex/contrib/animate/animate.sty @@ -13,7 +13,7 @@ \NeedsTeXFormat{LaTeX2e}[2020-10-01] -\def\@anim@version{2021/06/11} +\def\@anim@version{2021/08/19} \ProvidesPackage{animate} [\@anim@version\space PDF & SVG animations from files and inline graphics] @@ -793,10 +793,10 @@ \edef\@anim@arg{#1}% \ifx\@anim@EndLeft\@anim@arg% \@anim@xbutton{EndLeft}{% - [-1 0 0 1 15 0] concat \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% + [-1 0 0 1 15 0] concat \@anim@btnend}{#2}% \fi% \ifx\@anim@EndRight\@anim@arg% @@ -815,10 +815,10 @@ \fi% \ifx\@anim@PauseLeft\@anim@arg% \@anim@xbutton{PauseLeft}{% - [-1 0 0 1 15 0] concat \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% + [-1 0 0 1 15 0] concat \@anim@btnpause}{#2}% \fi% \ifx\@anim@PauseRight\@anim@arg% @@ -830,10 +830,10 @@ \fi% \ifx\@anim@PlayLeft\@anim@arg% \@anim@xbutton{PlayLeft}{% - [-1 0 0 1 15 0] concat \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% + [-1 0 0 1 15 0] concat \@anim@btnplay}{#2}% \fi% \ifx\@anim@PlayRight\@anim@arg% @@ -877,10 +877,10 @@ \fi% \ifx\@anim@StepLeft\@anim@arg% \@anim@xbutton{StepLeft}{% - [-1 0 0 1 15 0] concat \if@anim@dvisvgm\else\ifx\@anim@lscape\@anim@@lscape [0 1 -1 0 15 0] concat \fi\fi% + [-1 0 0 1 15 0] concat \@anim@btnstep}{#2}% \fi% \ifx\@anim@StepRight\@anim@arg% diff --git a/macros/latex/contrib/animate/animate.tex b/macros/latex/contrib/animate/animate.tex index 4721acff54..a5fb68d90f 100644 --- a/macros/latex/contrib/animate/animate.tex +++ b/macros/latex/contrib/animate/animate.tex @@ -5,14 +5,16 @@ % http://mirrors.ctan.org/macros/latex/base/lppl.txt % for the details of that license. % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\listfiles - -\RequirePackage{pdfmanagement-testphase} -\DeclareDocumentMetadata{ -% uncompress +%%% force dvi %%% +\ifdefined\outputmode\outputmode=0\fi +\ifdefined\pdfoutput\pdfoutput=0\fi +%%%%%%% pdfmanagement-testphase %%%%%% +\RequirePackage{pdfmanagement-testphase} % load the package +\DeclareDocumentMetadata % activates the PDF management interface +{ + %uncompress, } - +%%%%%% /pdfmanagement-testphase %%%%%% \documentclass[a4paper]{article} \frenchspacing \usepackage[buttonbg=0.9]{animate} @@ -35,7 +37,7 @@ \usepackage{parskip} \usepackage{tabls} \usepackage{multirow} -\usepackage[bookmarksnumbered,linktocpage]{hyperref} +\usepackage{hyperref} \usepackage[ocgcolorlinks]{ocgx2} \usepackage{amsmath} \usepackage{fancyvrb} @@ -65,7 +67,8 @@ pdfsubject={Documentation}, pdfauthor={Alexander Grahn}, pdfkeywords={\keywords}, - allcolors=blue + allcolors=blue, + bookmarksnumbered,linktocpage } \def\XeLaTeX{X\kern-.1667em\lower.5ex\hbox{\reflectbox{E}}\kern-.125em\LaTeX} @@ -1477,12 +1480,11 @@ I would like to thank François Lafont who discovered quite a few bugs and made \bibitem{chupin} Chupin, M.: \emph{Syracuse MetaPost/Animations.} URL: \href{http://melusine.eu.org/syracuse/metapost/animations/chupin/?idsec=scara}{\texttt{http://melusine.eu.org/}} \href{http://melusine.eu.org/syracuse/metapost/animations/chupin/?idsec=scara}{\texttt{syracuse/metapost/animations/chupin/?idsec=scara}} \bibitem{dvisvgm} \emph{dvisvgm: A fast DVI to SVG converter} URL: \url{http://dvisvgm.de} \bibitem{gilg05} Gilg, J.: PDF-Animationen. In: \emph{Die \TeX nische Kom\"odie}, Issue 4, 2005, pp.~30--37 -%%\bibitem{hol} Holeček, J.: \emph{Animations in a pdf\TeX-generated PDF}. URL: \url{http://www.fi.muni.cz/~xholecek/tex/pdfanim.xhtml} \bibitem{hol} Holeček, J.; Sojka, P.: Animations in pdf\TeX-generated PDF. In: \emph{\TeX, XML, and Digital Typography}, Springer, 2004, pp.~179--191. doi:10.1007/978-3-540-27773-6\textunderscore14 \bibitem{luque12} Luque, M.: \emph{PSTricks : applications.} URL: \url{http://pstricks.blogspot.com} \bibitem{media4svg} \emph{The media4svg Package}. URL: \url{http://www.ctan.org/pkg/media4svg} \bibitem{media9} \emph{The media9 Package}. URL: \url{http://www.ctan.org/pkg/media9} -\bibitem{texsx} \emph{Beamer: animate package and overlay}. URL: \href{https://tex.stackexchange.com/a/385209}{\texttt{https://tex.stackexchange.com}}\\\href{https://tex.stackexchange.com/a/385209}{\texttt{/a/385209}} +\bibitem{texsx} \emph{Beamer: animate package and overlay}. URL: \href{https://tex.stackexchange.com/a/385209}{\texttt{https://tex.stackexchange.com}}\\ \href{https://tex.stackexchange.com/a/385209}{\texttt{/a/385209}} \end{thebibliography} \end{document} diff --git a/macros/latex/contrib/easybook/easybook.dtx b/macros/latex/contrib/easybook/easybook.dtx index 778d47e92a..23cdec1049 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}{2021/08/16}{1.29} +\ProvidesExplClass{easybook}{2021/08/18}{1.29c} {Typeset Chinese theses or books} \bool_set_false:N \l__eb_compile_draft_bool @@ -63,7 +63,7 @@ } \ProcessKeysOptions{easybook} -\PassOptionsToPackage{CJKmath,quiet}{xeCJK} +\PassOptionsToPackage{no-math,quiet,CJKmath}{xeCJK} \eb_put_ctexbook:n { \g__eb_options_clist } \LoadClass[UTF8]{ctexbook} @@ -297,7 +297,7 @@ %<*package> \NeedsTeXFormat{LaTeX2e}[2020/10/01] \RequirePackage{l3keys2e,etoolbox} -\ProvidesExplPackage{easybase}{2021/08/16}{1.29} +\ProvidesExplPackage{easybase}{2021/08/18}{1.29c} {Typeset Chinese theses or books} \cs_generate_variant:Nn \dim_add:Nn { NV,Nv } @@ -1337,7 +1337,7 @@ \newcounter{bichapter} \newcounter{bisection}[bichapter] \newcounter{bisubsection}[bisection] -\cs_set_protected:Npn \eb_current_label:n #1 +\cs_new_protected:Npn \eb_current_label:n #1 { \tl_set:Nx \@currentlabel { @@ -1376,7 +1376,7 @@ {\tl_gset:Nn \eb@before@addbitoc@hook {#2}} {\tl_gput_right:Nn \eb@before@addbitoc@hook {#2}} } -\cs_set_protected:Npn \CTEX@addbitocline #1#2 +\cs_new_protected:Npn \CTEX@addbitocline #1#2 { \group_begin: \def\CTEX@prechapter{\CTEX@prebichapter} @@ -1589,7 +1589,7 @@ \cs_set_eq:NN \imki@indexlevel \use_none:n \setkeys{imkiindex}{noclearpage} \IfValueT{#3}{\keys_set:nn { eb/listoc } {#3}} - \tl_set:Nn \imki@indexheaders + \cs_set_protected:Npn \imki@indexheaders { \eb_title_number_intoc_spec:nn {#2} {#1} \cs_set_eq:NN \thispagestyle \use_none:n @@ -1677,7 +1677,7 @@ \cs_new_protected:Npn \eb_put_newtxmath:n #1 { \PassOptionsToPackage{#1}{newtxmath} } -\AfterPreamble +\eb_at_end_preamble:n { \str_case:VnT \l__eb_subfont_math_choice_tl { @@ -2131,7 +2131,7 @@ \group_begin: \tl_set_eq:NN \eb@toc@title \bibname \IfValueT{##3}{ \keys_set:nn { eb/listoc } {##3} } - \cs_set:Npn \bibsection + \cs_set_protected:Npn \bibsection { \eb_title_number_intoc_spec:nn {##2} {##1} \bool_if:NT \l__eb_toc_multi_column_bool @@ -2394,7 +2394,7 @@ } % %<*tcolorbox> -\ProvidesExplFile{eb-tcolorbox.cfg}{2021/08/16}{1.29} +\ProvidesExplFile{eb-tcolorbox.cfg}{2021/08/18}{1.29c} {Customization of tcolorbox for easybook} \tl_gset:Nn \eb@tc@line@skip { 0.5\baselineskip } diff --git a/macros/latex/contrib/easybook/easybook.pdf b/macros/latex/contrib/easybook/easybook.pdf index 59fc52c31d..281479c7dd 100644 Binary files a/macros/latex/contrib/easybook/easybook.pdf and b/macros/latex/contrib/easybook/easybook.pdf differ diff --git a/macros/latex/contrib/easybook/easybook.tex b/macros/latex/contrib/easybook/easybook.tex index 8485acc478..eba882bc04 100644 --- a/macros/latex/contrib/easybook/easybook.tex +++ b/macros/latex/contrib/easybook/easybook.tex @@ -12,8 +12,8 @@ name = easybook, color-scheme = blue, title = EASYBOOK 使用手册, - version = v1.29, - date = 2021/08/16, + version = v1.29c, + date = 2021/08/18, authors = 瞿毅, info = 排版简体中文学位论文和书籍, email = quee123@foxmail.com, @@ -316,7 +316,7 @@ \label{sec:interface options} \begin{commands} \command*{ctexset}[\marg{键值列表}] - \cls*{easybook} 扩展了 C\TeX 宏集 \hologo{LaTeX3} 风格键值的通用控制命令 \cs*{ctexset},接口选项同样可用它设置, 原有的 \meta{键值列表} 仍然可用。本文档类目前有九个模块用于实现常规的排版功能,如下表所示,它们既是统一接口 \cs*{ctexset} 的路径,也是相关模块的接口命令名: + \cls*{easybook} 扩展了 C\TeX 宏集 \hologo{LaTeX3} 风格键值的通用控制命令 \cs*{ctexset},接口选项同样可用它设置, 原有的 \meta{键值列表} 仍然可用。本文档类目前有 9 个模块用于实现常规的排版功能,如下表所示,它们既是统一接口 \cs*{ctexset} 的路径,也是相关模块的接口命令名: \begin{center} \begin{tabular}{*{5}{c}} \toprule @@ -547,7 +547,7 @@ \subsubsection{新建定理样式} \begin{commands} \command{declaretheorem}[\oarg{键值列表1}\marg{定理环境}\oarg{键值列表2}] - 声明新的定理环境命令,\cs{newtheorem} 命令与它等效。可选参数的 \meta{键值列表1} 与 \meta{键值列表2} 等效,用法与它们的同名命令一致。键值列表中常用的选项如下: + 声明新的定理环境命令,\cs{newtheorem} 命令与它等效。可选参数的 \meta{键值列表1} 与 \meta{键值列表2} 等效,用法与原来的同名命令一致。键值列表中常用的选项如下: \begin{options} \keyval*-{name}{定理名} 定理名的默认值是首字母大写的环境名称(英文标题)。 @@ -559,7 +559,7 @@ 选项的值为使用 \cs{declaretheoremstyle} 命令新定义的定理样式。 \end{options} \command{DeclareTheorem}[\marg{环境名}\oarg{英文标题}\marg{中文标题}\darg{盒子风格}\oarg{键值列表}] - 定理声明命令 \cs{DeclareTheorem} 更加便捷,同样定义一个新的定理环境,与 \cs{declaretheorem} 命令的键值列表支持相同的选项,但它们的区别有: + 定理声明命令 \cs{DeclareTheorem} 更加便捷,同样定义一个新的定理环境,\meta{键值列表} 中支持的选项与 \cs{declaretheorem} 命令相同,但它们的区别有: \begin{itemize} \item 中英文模式下标题不同,英文标题为可选项,默认为首字母大写的 \meta{环境名}。 \item 自动定义交叉引用的格式,引用标签前缀为定理名。 @@ -567,7 +567,7 @@ \item 新建定理环境默认使用的 \meta{定理样式} 为 \code{easy-theorem},而不是 \pkg*{thmtools} 默认样式。 \end{itemize} \command{declaretheoremstyle}[\oarg{键值列表1}\marg{定理样式}\oarg{键值列表2}] - 声明新的定理样式命令,键值列表支持上述 \module*{thmset} 模块中以及 \cs{declaretheorem} 的所有选项。可选参数的 \meta{键值列表1} 与 \meta{键值列表2} 等效,用法与它们的同名命令一致。 + 声明新的定理样式命令,键值列表支持上述 \module*{thmset} 模块中以及 \cs{declaretheorem} 的所有选项。可选参数的 \meta{键值列表1} 与 \meta{键值列表2} 等效,用法与原来的同名命令一致。 下面简单列举几个定理命令的用法,例如使用预置样式新建一个定理环境猜想: \begin{ctexexam} diff --git a/macros/latex/contrib/gamebooklib/Makefile b/macros/latex/contrib/gamebooklib/Makefile new file mode 100644 index 0000000000..eae8922072 --- /dev/null +++ b/macros/latex/contrib/gamebooklib/Makefile @@ -0,0 +1,20 @@ +default: gamebooklib_test.pdf gamebooklib.pdf tidy + +gamebooklib_test.pdf : gamebooklib_test.tex gamebooklib.sty + pdflatex \\nonstopmode\\input gamebooklib_test.tex && \ + pdflatex \\nonstopmode\\input gamebooklib_test.tex + +gamebooklib.sty : gamebooklib.dtx gamebooklib.ins + rm -f gamebooklib.sty && latex gamebooklib.ins + +gamebooklib.pdf : gamebooklib.sty gamebooklib.dtx + pdflatex \\nonstopmode\\input gamebooklib.dtx && \ + makeindex -s gglo.ist -o gamebooklib.gls gamebooklib.glo && \ + makeindex -s gind.ist -o gamebooklib.ind gamebooklib.idx && \ + pdflatex \\nonstopmode\\input gamebooklib.dtx + +tidy: + rm -f *.log *.ind *.idx *.glo *.gls *.aux *.ilg + +clean: tidy + rm -f *~ *.sty diff --git a/macros/latex/contrib/gamebooklib/README b/macros/latex/contrib/gamebooklib/README new file mode 100644 index 0000000000..01ac270ee2 --- /dev/null +++ b/macros/latex/contrib/gamebooklib/README @@ -0,0 +1,41 @@ +Copyright (C) 2021 by Robert J Lee + +This file 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. + + +The gamebooklib package, provides a convenient set of macros to assist +the author choosing to develop a gamebook. In particular, it aims to +solve 2 non-trivial issues: + +1) Writing a set of entries in order, then shuffling them in the +output routine, preserving reference links, and + +2) Allowing LaTeX to output footnotes at the end of an entry, in the +case where another entry falls below the footnote mark on the page. + + +This package uses the standard TeX .dtx+.ins install mechanism, +although a UNIX Makefile is provided for convenience to generate all +files. + +The file "gamebooklib_test.tex" provides a simple demonstration of +this library. + +The file "gamebooklib_countpagesperseed.sh" is a utility script using +bash, perl and pdflatex that will report on the number of pages for +your document, when entries are shuffled with different pseudorandom +seeds. This is useful if you have large objects such as graphics and +want to minimise needless white space. Further instructions are +provided in the header of that file. + +It is suggested that the gamebooklib_countpagesperseed.sh utility +should be placed on the system path for ease of use, or into any +utility scripts directory. \ No newline at end of file diff --git a/macros/latex/contrib/gamebooklib/gamebooklib.dtx b/macros/latex/contrib/gamebooklib/gamebooklib.dtx new file mode 100644 index 0000000000..eed4fc64c6 --- /dev/null +++ b/macros/latex/contrib/gamebooklib/gamebooklib.dtx @@ -0,0 +1,998 @@ +% \iffalse meta-comment +% +% Copyright (C) 2021 by Robert J Lee +% +% This file 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. +% +% \fi +% +% \iffalse +% \NeedsTeXFormat{LaTeX2e}[2005/12/01] +% \ProvidesPackage{gamebooklib} +% [2021/08/10 v1.0 gamebooklib typesetting] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{makeidx} +\usepackage[seed=1234]{lcg} +\usepackage{gamebooklib} +\usepackage{indentfirst} +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\makeindex +\begin{document} + \DocInput{gamebooklib.dtx} +\end{document} +% +% \fi +% +% \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 \~} +% +% \CheckSum{507} +% +% \changes{v1.0}{2021/08/10}{Initial Release} +% +% \GetFileInfo{gamebooklib.sty} +% +% \DoNotIndex{\let, \edef, \xdef, \relax, \newcommand} +% \DoNotIndex{\csname, \endcsname, \@M, \@MM, \@gobble} +% \DoNotIndex{\@ifnextchar, \@tmp, \@undefined, \\} +% \DoNotIndex{\arabic, \begin, \begingroup, \botmark, \break} +% \DoNotIndex{\@tmp, \@tmp@, \mytmp@, \tmp@, \tmp@@} +% \DoNotIndex{\centerline, \cs, \def, \detokenize, \else} +% \DoNotIndex{\endgroup, \equal, \expandafter, \fi} +% \DoNotIndex{\gdef, \global, \head, \hspace, \Huge, \if} +% \DoNotIndex{\ifcsname, \ifhmode, \ifnum, \ifthenelse, \ifvmode} +% \DoNotIndex{\interlinepenalty, \interlinefootnotepenalty} +% \DoNotIndex{\large, \leftskip, \mark, \NeedsTeXFormat} +% \DoNotIndex{\newcounter, \newenvironment, \newtoks, \noexpand} +% \DoNotIndex{\noindexnt, \nopagebreak, \not, \PackageInfo, \pagebreak} +% \DoNotIndex{\par, \PassOptionsToClass, \penalty, \ProcessOptions} +% \DoNotIndex{\protected@xdef, \ProvidesPackage, \rand, \requirecommand} +% \DoNotIndex{\RequirePackage, \rightskip, \rule, \setbox} +% \DoNotIndex{\setcounter, \stepcounter, \textbf, \typeout, \value} +% \DoNotIndex{\vbox, \unvbox, \vfill, \vspace, \vsize} +% \DoNotIndex{\WarningFilter, \whiledo, \Collect@Body, \CurrentOption} +% \DoNotIndex{\DeclareOption, \g@addto@macro, \the, \noindent} +% \DoNotIndex{\interfootnotelinepenalty, \marginpar, \myidx} +% \DoNotIndex{\addtocounter, \refstepcounter, \label} +% \DoNotIndex{\iffalse, \iftrue, \outputpenalty, \renewcommand} +% \DoNotIndex{\noshuffle, \verbose, \endpage, \footnote} +% +% \title{The Gamebooklib Package\thanks{This document corresponds to \textsf{Gamebooklib}~\fileversion, dated \filedate.}} +% \author{Robert J Lee \\ latex@rjlee.homelinux.org} +% +% \maketitle +% +% \begin{abstract} +% +% This package provides macros and environments to allow the user to +% typeset a series of cross-referenced, numbered ``entries'', +% shuffled into random order +% +% \end{abstract} +% +% \section{Introduction} +% +% This package was written to allow the typesetting of gamebooks. +% +% A gamebook is a book divided into ``entries'' (which may be a single +% paragraph or longer), each with a sequentially numbered value. At +% the end of each entry, a link to one or more other numbered +% entries is given; the reader selects one and they follow through +% the story in this order. gamebooks traditionally start at the +% entry numbered~``1'' and some gamebooks have multiple endings, +% with the final section representing a success or victory for the +% reader. +% +% In particular, this package handles two technical challenges which +% are tricky to solve with \LaTeX\ directly: writing the ``entries'' +% in order but presenting them in a randomised order; and presenting +% footnotes at the end of each ``entry'', numbered in the order in +% which they appear, not the order in which they are written. +% +% Aside from shuffling the paragraphs and fixing the handling of +% footnotes, this package provides little help for the actual +% typesetting of gamebook entries. For this, please consider using +% Andr\'e Miede's |gamebook| package, available on +% CTAN\footnote{\texttt{https://www.ctan.org/pkg/gamebook}}. That +% package is orthogonal to this one; both may be used together. +% +% \section*{Terminology} +% +% For the purposes of this document, the term \textit{entry} means a +% numbered section of text. This term helps describe the +% common format of a gamebook, while avoiding confusion with the terms +% \textit{paragraph} and a \textit{section}, both of which +% already have a clear definition. +% +% The term \textit{gamebook} means a book consisting of numbered +% sections, typically presented in a non-linear order with a +% tree or graph of possible reading options. +% +% \section*{Usage} +% +% To load the class, use |\usepackage[|\textit{options}|]{gamebook}| +% +% The class options are described below; |[footnotes]| is normally a +% good choice, although there are some limitations. +% +% The user simply writes entries like this inside the document: +% \begin{verbatim} +% \begin{gentry}{codea} +% This is the first entry +% +% Turn to \turnto{codeb} +% \end{gentry} +% +% \begin{gentry}[123]{codeb}[title] +% This is the second and final entry.\par +% To play again, turn to \turnto{codea} +% \end{gentry} +% +% % Output: +% \thegentries +% \end{verbatim} +% +% Here, two entries are defined, and then output. +% +% The first entry is given a label of |gentry:codea|, and the +% \cs{turnto\{codea\}} in the second entry generates a link back to +% that label. +% +% As |entry| is a common term likely to conflict with other +% environments, the environment to declare an entry has been named +% |gentry| (gamebook entry) instead. +% +% Sometimes it is convenient, when writing an entry, to give it a fixed +% index in the text. The first optional argument in the second entry +% --- |[123]| --- fixes the entry at that position during +% shuffling. This is implemented by iterating over each entry and +% swapping it with that index. Duplicates are not currently checked +% for, but they would not be lost; if two entries are defined with the +% same fixed index, one will end up somewhere else in the text. +% +% The first and last entries are automatically fixed without +% needing to specify the optional number. +% +% Specifying the optional number as a value greater than or equal to +% the number of entries, or less than~2, is not recommended. (Yes, +% this example used |123|, which is beyond the number of entries. This +% was done to show the syntax). +% +% The second optional argument is a title to be displayed alongside +% the numerical value. +% +% Finally, the command \cs{thegentries} will output all entries defined so +% far, handling shuffling and footnotes. +% +% \DescribeMacro{\gentryheader}\marg{counterIdx}\marg{fixedIdx}\marg{code}\marg{title} +% +% Users may also want to redefine \cs{gentryheader} to change how the +% entries are displayed. The initial version is quite basic and +% intended for debugging; users should use \cs{renewcommand} to change +% it to something more pleasant. +% +% Here's one suggestion, using packages from CTAN. It works well if you have either a +% title, or at least 2 lines of text before the first paragraph break +% inside the |gentry|. +% +% +% It also requires near the start of the document: +% \begin{verbatim} +% \usepackage{lettrine} +% \usepackage{etoolbox} +% \usepackage{color} +% \end{verbatim} +% And this anywhere before \cs{thegentries}: +% \begin{verbatim} +% \renewcommand{\LettrineFontHook}{% +% \color[gray]{0.5}\fontfamily{ppl}\fontseries{bx}} +% \renewcommand{\gentryheader}[4]{ +% \lettrine[lines=3,lhang=0.2,loversize=0.2]{\raisebox{0.1em}{#1}}% +% {\textbf{\Large\textbf{\raisebox{0.3em}{~#4} +% }}}% +% \ifstrempty{#1}{}{\linebreak\mbox{}~}} +% \end{verbatim} +% On the last line, \cs{mbox} stops the \cs{parindent} space being +% ignored; the $\sim$ brings it back up to the expected spacing. +% +% \section*{Package options} +% +% These options can be specified as a comma-separated list to the +% \cs{usepackage} line. +% +% \begin{macro}{footnote} +% \changes{v1.0}{2021/08/10}{Footnote option} +% The |footnote| option causes \LaTeX\ to output footnotes at the end +% of each entry, or the end of each page, whichever comes first after +% the footnote mark. +% +% There are some limitations, described below. +% +% Support for other packages that affect footnotes is limited. If +% using |hyperref|, it is recommended to pass |[hyperfootnotes=false]| +% to avoid broken links. +% \end{macro} +% +% \begin{macro}{noshuffle} +% \changes{v1.0}{2021/08/10}{Noshuffle option} +% In general, it's easier to write gamebooks in a more linear fashion, +% in which related entries are kept together. But this is much less +% fun to play, as it's too easy for the reader to simply read the +% adjacent eentries to decide what to do. +% For this reason, this package shuffles the output entries by +% default. The first and last entries are never shuffled. +% +% Sometimes, perhaps for proofreading, you may not want the entries +% to be shuffled. In this case, you can use the |noshuffle| option. +% \end{macro} +% +% \begin{macro}{verbose} +% \changes{v1.0}{2021/08/10}{Verbose option} +% This macro causes the package to output information messages about +% what it's doing to the log file. This is not generally too useful, but it does +% include a mapping of the original paragraph indexes to their sorted +% positons, which may be useful to keep for handling proofreading +% corrections. +% \end{macro} +% +% \begin{macro}{endpage} +% \changes{v1.0}{2021/08/10}{Endpage option} +% Puts the last entry on a page on its own. This typically produces a +% better ``winning'' feel for reaching the last entry, but it can also +% produce documents with ugly spacing, so it's recommended to try it +% each way and see which works better for your text. +% \end{macro} +% +% +% \section*{Footnotes} +% +% When typesetting a gamebook with footnotes, it is confusing if they +% migrate to the bottom of each page, as the footnote becomes visually +% detached from the entry to which it relates. Some effort has been taken to +% ensure that footnotes can be typeset at the bottom of the page on which +% the mark appears, or the bottom of each entry, whichever comes +% first. +% +% However, this implementation has some limitations: +% +% \begin{itemize} +% \item Footnotes are not expanded until they are typeset. +% \item As a consequence, attaching one footnote to another with the +% use of \cs{footnotemark} within a \cs{footnote} argument will not +% advance the counter in time, so \cs{footnotetext} may not behave as +% you expect unless it is also set inside the first footnote's text. +% \item Footnotes at the end of the page will not be broken across +% pages. Putting sufficient text into footnotes will cause the page +% to overflow. +% \item Where the footnote \textbf{mark} appears at the very end of a page, +% the footnote \textbf{text} may be set at the top of the subsequent +% page. \TeX\ is asked not to break the page there, but this influence +% is limited. It may be possible for the author to avoid this, eg by +% adding a rubber length to the interline spacing (it may be easier to +% simply choose a different seed value for the |lcg| package to +% reshuffle). +% \item If you have a lot of rubber space in the text, or +% variably-sized items, \LaTeX\ may expand the footnote at the end of +% the entry before it works out where to put the page break. In this +% case, the footnote will appear on the wrong page. The macro +% \cs{noentryfoot} is provided to allow the author to fix this case. +% \item Support for other footnotes packages may be limited and the +% behaviour of packages like |footnote|, |endnotes|, |footmisx|, +% |fnote|, |dblfnote| \textit{etc} may be affected. +% \item If using the |hyperref| package, it is recommended to pass the +% option |hyperfootnotes=false| to that package, as the footnote links +% will be incorrect. +% \item The package uses \TeX\ \cs{mark}s to indicate which footnotes +% should appear on each page. Because \TeX\ supports only one set of +% marks, this would break any other package or usage of \cs{mark} +% while a gamebook was being output. +% \item Because \cs{mark} does not escape a floating environment, such +% as |minipage|, it is likely that this footnote implementation will +% not work as expected if the gamebook or \cs{footnote} is set in a |minipage| or +% similar. +% \item Each footnote is evaluated in a group. Just conceivably, this +% might affect the behaviour of some macros that affect the document +% beyond the footnote. +% \item We rely on some non-``public'' macros, such as \cs{@mpfn} and +% \cs{@footnotetext} defined by \LaTeX\ standard document +% classes. Other document classes may override these, which would +% override this package's footnotes too. +% \end{itemize} +% +% For this reason, the improved footnote handling is only enabled if +% you pass the |footnote| option, and only while the environment is +% active. +% +% \section*{Implementation} +%\StopEventually{\PrintChanges \pagebreak[4] \PrintIndex} +% +% \begin{macrocode} +\ProvidesPackage{gamebooklib}[2021/08/10 Gamebook by R Lee latex@rjlee.homelinux.org] +% \end{macrocode} +% We need \LaTeXe, for the extra token registers. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e}[1994/06/01] +% \end{macrocode} +% \begin{macro}{verbose} +% The package option |verbose| enables detailed logging. +% Logging is via the macro \cs{gamebook@info}, which throws away detail messages +% unless the |verbose| option is given. +% \begin{macrocode} +\newcommand{\gamebook@info}[1]{}% +\DeclareOption{verbose}{% + \renewcommand{\gamebook@info}[1]{\PackageInfo{gamebooklib}{#1}}% + \gamebook@info{Gamebook Library package is logging}}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{endpage} +% The |endpage| option puts the last entry on its own page. This can +% work better when the last entryraph is about a page long, and also +% the final ``winning'' entry of the gamebook. +% \begin{macrocode} +\newcommand\gamebook@beforelast{} +\DeclareOption{endpage}{% + \renewcommand\gamebook@beforelast{\eject}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{footnote} +% The |footnote| option enables our footnote processing, to throw out +% footnotes at the end of each |gentry| so that they don't appear to be +% against subsequent entries for that page. +% +% This is genearlly recommended, unless you have a reason to turn it +% off (such as a conflicting package). It's disabled by default +% because it could cause unexpected errors. +% \begin{macrocode} +\def\if@gamebook@footnotes{\iffalse} +\DeclareOption{footnote}{% + \gdef\if@gamebook@footnotes{\iftrue}% + \gamebook@info{Gamebook Library footnotes per gamebook entry}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{noshuffle} +% \begin{macrocode} +\def\if@gamebook@shuffle{\iftrue} +\DeclareOption{noshuffle}{% + \gdef\if@gamebook@shuffle{\iffalse}% + \gamebook@info{Gamebook Library entries output in order}% +}% +% \end{macrocode} +% \end{macro} +% +% All unknown options are passed to |lcg|, as it's our only dependency with options. +% It's suggested that users specify a value for ``seed'' for stable +% builds, by adding the following before including this package: +% +% |\usepackage[seed=123]{lcg}| +% \begin{macrocode} +\DeclareOption*{% + \typeout{Current option: \CurrentOption}% + \PassOptionsToClass{\CurrentOption}{lcg}% +}% +\ProcessOptions\relax% +% \end{macrocode} +% We need to capture environment contents +% \begin{macrocode} +\RequirePackage{environ}% +% \end{macrocode} +% |Macroswap|: used to swap the commands that evaluate the macros +% \begin{macrocode} +\RequirePackage{macroswap}% +% \end{macrocode} +% |Ifthen| makes branching and loops a little easier +% \begin{macrocode} +\RequirePackage{ifthen} +% \end{macrocode} +% |LCG|: random numbers for the shuffle +% \begin{macrocode} +\RequirePackage{lcg}% +% \end{macrocode} +% |Silence| is used to suppress a warning from~|lcg| that gamebook is +% \textbf{not} wasting counter registers. |debrief| ensures that the +% user is at least told than warnings were suppressed. +% +% To see the warnings, put the following line before +% |\usepackage{gamebook}|: +% +% |\usepackage[debrief,showwarnings]{silence}|: +% \begin{macrocode} +\RequirePackage[debrief]{silence}% +% \end{macrocode} +% +% Let's count the entries we're reading in so we can build up token +% registers. +% \begin{macrocode} +\newcounter{gentryctr}% +\setcounter{gentryctr}{0}% +% \end{macrocode} +% +% \begin{environment}{gentry}\oarg{fixedIdx}\marg{code}\oarg{title} +% First, we need to parse the optional arguments. +% +% When we say \cs{begin}\{gentry\}, \LaTeX\ does some stuff ending in \cs{gentry} +% so we redefine \cs{gentry} to take an optional argument and delegate to \cs{@gentry} +% \begin{macrocode} +\newcommand{\gentry}[1][]{\@gentry{#1}}% +% \end{macrocode} +% \cs{gentry} just makes the first argument mandatory. +% +% \cs{@gentry} defines \cs{gentryidx} and \cs{gentrycode}, which can be used in +% the body of the \cs{gentry} environment to supply the unsorted index +% number and the current entry's unique code. +% +% NB: If you define two entries with the same code, \LaTeX\ will print +% out a "multiply defined" label warning. +% \begin{macrocode} +\newenvironment{@gentry}[2]{% + \def\gentryidx{#1}% + \def\gentrycode{#2}% + \@@gentry% +}{\ignorespacesandallpars% +}% +% \end{macrocode} +% \cs{@@gentry} then reads in the optional title argument, storing it in the \cs{gentrytitle} +% macro to supply the unsorted index number and the current entry's code respectively. +% \begin{macrocode} +\newcommand{\@@gentry}[1][]{% + \def\gentrytitle{#1}% + \stepcounter{gentryctr}% +% \end{macrocode} +% For fixed entries, define a macro to hold the requested index +% \begin{macrocode} + \ifthenelse{\equal{\gentryidx}{}}{}{% + \expandafter\xdef\csname fixedat\arabic{gentryctr}% + \endcsname{\gentryidx}% + }% + \expandafter\global\expandafter\newtoks\expandafter{% + \csname paratok\arabic{gentryctr}\endcsname}{ }% + \Collect@Body\gentry@store% +% \end{macrocode} +% This was supposed to discard any blank lines at the end of the +% |gentry| environment, but it still left odd spacing in the +% output somehow, and sometimes produced weird error messages about +% |\inaccessible| and |\head|. Removed for now. +% \begin{macrocode} +% \ignorespacesandallpars% +} +% \end{macrocode} +% Store the collected environment contents for \cs{thegentries} to output: +% This uses the token register \cs{gentry$N$}, where $N$ is the +% unsorted index of this entry. +% Later, we'll change the values of the $N$ bit of \cs{gentry$N$} +% macros when we shuffle (the underlying token registers stay the same). +% +% This relies on \cs{refstepcounter}\marg{gentryctr} before expanded +% before this macro. The label |gentry:\gentrycode| is thus set to the +% current index of the final output entry. +% \begin{macrocode} +\newcommand{\gentry@store}[1]{% + \edef\head{\noexpand\begingroup\noexpand\gentryheader% + {\arabic{gentryctr}}{\gentryidx}{\gentrycode}{\gentrytitle}% + \noexpand\label{gentry:\gentrycode}% + }% + \global\expandafter\csname paratok\arabic{gentryctr}\endcsname=% +% \end{macrocode} +% Output the header, the environment token list, flush any footnotes (if applicable) then the inter-gentry footer. +% \begin{macrocode} + \expandafter{\head #1% + \outputfootnotes@endgentry% + \gentryfooter\endgroup}% +}% +% \end{macrocode} +% \end{environment} +% +% \DescribeMacro{\gentry@footnotespergentry} +% This macro is executed inside the |gentry| group and sets up the +% commands to be run to allow footnotes. It is only expanded if +% \cs{if@gamebook@footnotes} is true, \textit{ie} the |footnotes| +% option is given. +% \begin{macrocode} +\newcommand{\gentry@footnotespergentry}{} +% \end{macrocode} +% +% \DescribeMacro{\thegentries} +% +% This macro shuffles the entries as required, then expands to them in +% the correct order. +% \begin{macrocode} +\newcommand{\thegentries}{% +% \end{macrocode} +% This command is in a group so that the output routine resets. +% +% The expansion of \cs{gentry@footnotespergentry} only happens if the +% |footnote| option was given; it sets up the output routine while the +% gamebook is running. +% \begin{macrocode} +\begingroup% + \if@gamebook@footnotes\gentry@footnotespergentry\fi% +% \end{macrocode} +% To begin, let's record the number of entries. This may come in +% useful. Note that you can use this macro in the |gentry| environment, +% because that's not been expanded yet. +% \begin{macrocode} + \xdef\gentrycount{\arabic{gentryctr}}% +% \end{macrocode} +% +% The next thing is to perform some surgery on LCG. +% This cuts out an \textbf{annoying} warning, hopefully more reliably +% than replacing the definition of \cs{p@stkeysr@nd}. +% The warning is simply that this package doesn't waste another +% counter every time it changes the random limits (which happens a lot +% during Knuth shuffle): +% \begin{macrocode} + \WarningFilter{lcg}{Using an already existing counter rand}% +% \end{macrocode} +% +% \subsection*{The output routine and end-of-page footnotes} +% The idea is to keep footnotes always on the same page as their mark where possible. +% +% \LaTeX\ does lots of fun things with the output routine, which we +% want to keep. So grab a copy of whatever the code is currently doing: +% +% Here I'm using the \cs{edef} trick to expand \cs{the}\cs{output} into a token register, because using a macro +% causes a weird error about an ``|{|'' after ``\cs{the}''. +% \begin{macrocode} +\newtoks\gentry@oldoutput{}% +\edef\mytmp@{\noexpand\gentry@oldoutput={\the\output}}\mytmp@% +% \end{macrocode} +% For the footnotes, if we reach the end of a page without outputting +% them, we need to flush them. +% +% \cs{output} is the output routine. It takes the page built up in +% \cs{box255}, annotates it with headers, footers etc, then ships it +% out. For our purposes, we only need to append the footnotes to the +% bottom of \cs{box255}. +% \begin{macrocode} +\if@gamebook@footnotes\output={% +% \end{macrocode} +% The \cs{outputpenalty} tells us why the output routine was called; generally, it's invoked whenever +% a new floatable environment is generated, or when a page is full. Anything less than -1000 means that +% the page was filled, so we should add any footnotes only in this case. +% \begin{macrocode} + \ifnum\outputpenalty<-\@M\else% + \edef\tmp@{footnotetoks\botmark} + \expandafter\ifcsname footnotetoks\botmark\endcsname% + \global\setbox255=\vbox to \vsize{% + \unvbox255\vfill\outputfootnotes@endpage}% + \fi% + \fi% + \the\gentry@oldoutput +}\fi% +% \end{macrocode} +% +% \subsection*{The shuffling algorithm} +% +% \TeX\ has well beyond 255 token registers these days, so don't +% bother to check that limit. +% +% The LCG package provides a suitable pseudo-random number generator. +% What we want is a repeatable series of numbers. +% +%\begin{enumerate} +% \item Work out how many entries there are~($N$). Provided \cs{thegentries} is +% called at the end, this is just the value of |gentryctr| +% \item Declare a set of token registers named \cs{paratoks}$n$, where $n$ is +% each integer 1\dots$N$ inclusive. These will hold the contents of the entry. +% \item Declare a set of macros named \cs{paraidx}$n$, where $n$ is +% each integer 1\dots$N$ inclusive, initialised to $n$. These will hold the number of the entry. +% \item Shuffle elements $\{2:N-1\}$, in that array. For $i=2$ through $N-2$ +% \begin{enumerate} +% \item Let $R$ be a random number between $i$ and $N-1$ inclusive +% \item If $R\ne i$ then swap macros \cs{gentrytoks}$R$ and \cs{gentrytoks}$i$ +% \item If $R\ne i$ then swap macros \cs{paraIdx}$R$ and \cs{gentryidx}$i$ +% \end{enumerate} +% \item For $i=1:n$, output token reg $i$ +%\end{enumerate} +% +% Define macros \cs{csname}~|paraIdx|$N'$\cs{endcsname} containing the arabic +% original page number to be put out on the $N'$th output ``page'' +% \begin{macrocode} + \xdef\gentrycount{\arabic{gentryctr}}% +% \end{macrocode} +% we can reuse |gentryctr|; we've finished this set of paras and +% kept the total count. +% \begin{macrocode} + \setcounter{gentryctr}{0}% +% \end{macrocode} +% If there are fewer than 3 entries, don't try and shuffle. +% \begin{macrocode} + \ifthenelse{\gentrycount<3}{}{%SHUFFLE START + \whiledo{\not{\value{gentryctr}>\gentrycount}}{% + \edef\myidx{\arabic{gentryctr}}% + \expandafter\xdef\csname paraIdx\myidx\endcsname{\myidx}% + \stepcounter{gentryctr}% + }% +% \end{macrocode} +% Don't renumber para~1 or \cs{gentrycount}; Knuth-shuffle the rest +% NB: we stop at \cs{gentrycount}$-2$, because \cs{gentrycount}$-1$ would only shuffle +% with itself. +% \begin{macrocode} + \if@gamebook@shuffle + \setcounter{gentryctr}{2}% + \setcounter{rand}{\gentrycount}% + \addtocounter{rand}{-1}\edef% + \stoppoint{\arabic{rand}}% + \chgrand[last=\stoppoint]% + \whiledo{\value{gentryctr}<\stoppoint}{% +% \end{macrocode} +% If this is to be swapped with a fixed position, skip it +% \begin{macrocode} + \edef\myidx{\arabic{gentryctr}}% + \expandafter\ifcsname fixedat\myidx\endcsname% + \gamebook@info{Not shuffling \myidx; fixed pos}% + \stepcounter{gentryctr}% + \else% + \gamebook@info{Shuffling \myidx}% + \stepcounter{gentryctr}% + \edef\nextidx{\arabic{gentryctr}}% +% \end{macrocode} +% If we've hit an entry with fixed position, we may as well skip it +% \begin{macrocode} + \expandafter\ifcsname fixedto\arabic{rand}\endcsname\else% + \chgrand[first=\nextidx]% + \rand% + \gamebook@info{Shuffling \myidx to \arabic{rand}}% + \macroswap{paraIdx\myidx}{paraIdx\arabic{rand}}% + \fi% + \fi% + }% +% \end{macrocode} +% Now move fixed entries into their final place: +% \begin{macrocode} + \setcounter{gentryctr}{2}% + \whiledo{\value{gentryctr}<\stoppoint}{% + \edef\myidx{\arabic{gentryctr}}% + \expandafter\ifcsname fixedat\myidx\endcsname% + \expandafter\edef\expandafter\mydest\expandafter% + {\expandafter\csname fixedat\myidx\endcsname}% + \gamebook@info{MOVING FIXED GAMEBOOK ENTRY INTO PLACE: \myidx -> \mydest}% + \macroswap{paraIdx\myidx}% + {paraIdx\expandafter\csname fixedat\myidx\endcsname}% + \fi% + \stepcounter{gentryctr}% + }}\fi%SHUFFLE END + \gamebook@info{Shuffled! Gentry order:}% + \setcounter{gentryctr}{1}% + \whiledo{\not{\value{gentryctr}>\gentrycount}}{% + \edef\myidx{\arabic{gentryctr}}% + \gamebook@info{\myidx -> \csname paraIdx\myidx\endcsname}% + \stepcounter{gentryctr}% + }% +% \end{macrocode} +% +% We can reuse the same counter again to output +% \begin{macrocode} + \setcounter{gentryctr}{0}% + \gamebook@info{Outputting \gentrycount\ gamebook entries}% + \whiledo{\value{gentryctr}<\gentrycount}{% +% \end{macrocode} +% Use refstepcounter in the loop to allow \cs{label} to work as expected. +% \begin{macrocode} + \refstepcounter{gentryctr}% +% \end{macrocode} +% Keep last entry on its own page +% \begin{macrocode} + \ifthenelse{\value{gentryctr}=\gentrycount}{% + \gamebook@beforelast% + }{}% + \edef\myidx{\arabic{gentryctr}}% + \xdef\youridx{\csname paraIdx\myidx\endcsname}% + \gamebook@info{Output gentry \myidx\ of \gentrycount,% + original idx \youridx}% +% \end{macrocode} +% Output the stored entry body, stripping any extraneous space: +% \begin{macrocode} + \the\csname paratok\youridx\endcsname% + }% +% \end{macrocode} +% Finally, we clear the registers and reset the counter in case we want to start again +% \begin{macrocode} + \gamebook@info{All gamebook entries added to main vertical list}% + \setcounter{gentryctr}{1}% + \whiledo{\not{\value{gentryctr}>\gentrycount}}{% + \edef\myidx{\arabic{gentryctr}}% + \expandafter\global\expandafter\let% + \csname paratok\myidx\endcsname\@undefined% + \expandafter\ifcsname fixedat\myidx\endcsname% + \expandafter\global\expandafter\let% + \csname fixedat\myidx\endcsname\@undefined% + \fi% + \stepcounter{gentryctr}% + }% + \setcounter{gentryctr}{0}% + \eject + \endgroup% +}% +% \end{macrocode} +% The final \cs{eject} ensures that the output routine has flushed as +% many pages as it can, before the output routine is reset again. +% +% \DescribeMacro{\gentryheader}\marg{counterIdx}\marg{fixedIdx}\marg{code}\marg{title} +% +% This macro is called before outputting the header. Its +% job is to format whatever header information the user wants to see +% on each entry; generally, this will be the page number. +% +% It takes 4 parameters: +%\begin{enumerate} +%\item The \textit{unshuffled} index value (to help an author find an +% entry in the original text) +%\item The \textit{fixed} index value, if any; otherwise an empty argument +%\item The user-entered unique code for this entry +%\item The user-supplied title, if any; otherwise an empty argument +%\end{enumerate} +% +% The value of the output index can be obtained with |\arabic{gentryctr}| +% \begin{macrocode} +\newcommand{\gentryheader}[4]{% + \noindent\textbf{\Huge\arabic{gentryctr}\large\ #4}% + \nopagebreak% + \vspace{0.3em}% + \nopagebreak% + \par% + \marginpar{#3}% +}% +% \end{macrocode} +% +% \DescribeMacro{\gentryfooter} +% This takes no arguments and is simply expanded after the entry is typeset. The default adds some vertical +% space and a simple separator. +% +% \begin{macrocode} +\newcommand{\gentryfooter}{% + \par\vspace{2em}\centerline{---}\vspace{2em plus 1in}\par% +}% +% \end{macrocode} +% +% \DescribeMacro{\ignorespacesandallpars@} +% This is a technique described on StackExchange: +% +% {\small https://tex.stackexchange.com/questions/179016/\\ignore-spaces-and-pars-after-an-environment\#179034} +% +% This is used to ensure that extra space at the start and end of the |gentry| +% environment is ignored. +% +% \begin{macrocode} +\def\ignorespacesandallpars@{% + \@ifnextchar\par% + {\expandafter\ignorespacesandallpars\@gobble}% + {}% +}% +% \end{macrocode} +% +% \DescribeMacro{\@footnotetext}\marg{token register} +% Token registers to hold each footnote. +% +% Each footnote is held in its own token register, so that we can control +% which footnotes appear on each page. +% +% \LaTeX\ would normally use saveboxes to store footnotes, but I +% prefer to hold off on expanding them until we know which page +% they're to be expanded on, which saves some difficulties (and +% perhaps creates others). +% +% To start with, modify \LaTeX's \cs{@makefnmark} to output a mark for +% the footnote, holding its index. This tells the output routine which +% footnotes to include at the end of the page. The +% \cs{in@out} macro is only defined when outputting footnotes, so +% suppresses this mark when we don't need it. +% \begin{macrocode} +\g@addto@macro{\@makefnmark}{% + \ifcsname in@out\endcsname\else% + \mark{\arabic{\@mpfn}}% + \fi% +}% +% \end{macrocode} +% +% The \cs{footnotetext@save} is a convenience that takes the the +% footnote counter value in the first argument, the token register as +% a second argument, and the token list (footnote text) as the third. +% \begin{macrocode} +\g@addto@macro{\gentry@footnotespergentry}{% +\newcommand{\@footnotetext@save}[3]{% + \global\newtoks#2{}% + \global#2={\noindent\@footnotemark{}#3}% +}}% +% \end{macrocode} +% \cs{@footnotetext@save} unpacks the arguments for +% \cs{@footnotetext@save@}. This one uses the value of the \cs{@mpfn} +% counter to unpack the footnote counter, the token register (full csname) as +% the first argument, and the token list (footnote text) as the second. +% \begin{macrocode} +\g@addto@macro{\gentry@footnotespergentry}{% +\newcommand{\@footnotetext@save@}[2]{% + \edef\@tmp@{\expandafter\arabic{\@mpfn}}% + \expandafter\@footnotetext@save\expandafter{\@tmp@}{#1}{#2}% +}}% +% \end{macrocode} +% Footnotes are built in a group, so that \cs{in@out} can be defined +% locally to indicate that footnotes are being built (which stops +% spurious \cs{mark}s). +% \begin{macrocode} +\g@addto@macro{\gentry@footnotespergentry}{% +\renewcommand{\@footnotetext}[1]{% + \begingroup% + \def\in@out{}% flag that we're building footnotes + \edef\@tmp{\expandafter\csname footnotetoks\arabic{\@mpfn}\endcsname}% + \expandafter\@footnotetext@save@\expandafter{\@tmp}{% + % This fixes up the use of \cs{footnotemark} within footnotes: + #1}% + \endgroup% +}}% +% \end{macrocode} +% +% \DescribeMacro{\outputfootnotes}\marg{maxIdx} +% +% Command to output the footnotes, which are just in \cs{footnotetoks$N$} +% for now. +% +% An end user can call this at any point in the text to set out the footnotes. +% +% This macro takes one argument, being the maximum index of footnotes to output, inclusive. +% Footnotes after this index will be excluded. If not provided, the +% value provided by the counter \cs{@mfpn}, which in the default +% \LaTeX\ counter, will be used. +% \begin{macrocode} +\newcounter{fncounter}% +\newcommand{\outputfootnotes}[1]{% + \begingroup% + \def\in@out{}% flag that footnotes are outputting; suppresses marks + \setcounter{fncounter}{1} +% \end{macrocode} +% Called in vertical mode, and don't want to throw a page break. +% +% I'm not sure how \LaTeX\ renders the footnote rule exactly, so I'm just using my own. +% \begin{macrocode} + \def\footnote@rule{% +% \end{macrocode} +% The next line comess from the TUGboat suggestions, and protect against various user changes +% \begin{macrocode} + \leftskip=0pt\rightskip=0pt\interlinepenalty=1000% + \penalty-1000% + \vspace{1pt plus 2pt minus 0.5pt}% + \hspace{-0.5in}\rule{1.5in}{0.4pt}\\% + }% +% \end{macrocode} +% Invoke the output routine. This attempts to stop the output routine +% being invoked while we're adding the footnote rule, which could +% cause a blank footnote to appear. +% +% Instead, it means some footnotes could appear on the subsequent +% page. To guard against this, footnotes are set into a \cs{vbox} +% to prevent page breaking. +% +% The macro \cs{footnote@rule} is output before each footnote. The +% first time, it outputs a divider rule; subsequently, it just throws +% a new paragraph to keep footnotes on separate lines. +% +% The next line comess from the TUGboat suggestions, and protect against various user changes +% \begin{macrocode} + \outputpenalty=-\@MM\break% + \vbox{% + \whiledo{\not{\value{fncounter}>#1}}{% +% \end{macrocode} +% We are now looping over all possible entry numbers, in +% order. Some will already have been output, but we check them all +% anyway (it doesn't take much time). +% +% First, we check if the macro exists. If it does, it must contain the +% value of the token register. +% +% Next, we make sure that the token register has contents. +% +% \begin{macrocode} + \expandafter\ifcsname footnotetoks\arabic{fncounter}\endcsname% + \edef\tmp@@{\csname footnotetoks\arabic{fncounter}\endcsname}% +% \end{macrocode} +% This \cs{detokenize} black magic tests if a token reg is actually +% empty: +% +% https://tex.stackexchange.com/questions/263733/\\whats-the-best-practice-way-to-test-whether-parameter-is-empty +% \begin{macrocode} + \expandafter\if\expandafter\relax\expandafter% + \detokenize\expandafter{\the\tmp@@}\relax\else% + \footnote@rule\gdef\footnote@rule{\ifvmode\else\par\fi}% + \interlinepenalty\interfootnotelinepenalty% +% \end{macrocode} +% Actually output the footnotes. +% +% Having output the footnote, clear the token register (to save +% memory), then use \cs{let} to clear the definition of the +% macro. This ensures that we don't try to output the same footnote +% twice (at page end and entry end). +% \begin{macrocode} + \expandafter\the\tmp@@% + \global\expandafter\tmp@@={}% + \expandafter\let\tmp@@\@undefined% + \fi\fi% + \stepcounter{fncounter}% + }% + }% + \endgroup% +}% +% \end{macrocode} +% \LaTeX\ works by building up a little more than a page, then calling the output routine. +% The output routine then decides where to put the page end from the built-up material. +% If there is a footnote mark, it could come after the page end, so we can't rely on the +% fact that there's footnote register to determine if we should output footnotes or not. +% The edge case is: if the footnote mark is held back for the next page, the footnote text +% would appear on the footer of the page where being built when the mark was expanded, which +% is the page before the footnote. +% +% One fix for this is to have each footnote mark in the main body of +% the text output a \cs{mark} containing the footnote's counter value, +% and output the footnotes only to \cs{botmark}, which is the last +% \cs{mark} actually typeset on the page. +% +% (see https://www.tug.org/TUGboat/Articles/tb11-4/tb30salomon.pdf, +% page 598, to read around footnotes). +% +% \DescribeMacro{\outputfootnotes@endgentry} +% This macro is called at the end of each |gentry|. It switches into +% vertical mode (as ending |gentry| doesn't throw a \cs{break} or line +% end by itself), then we output all footnotes so far (by reading the +% footnote counter \cs{@mpfn}, as this is ``sequential''). +% \begin{macrocode} +\newcommand{\outputfootnotes@endgentry}{% + \if@gamebook@footnotes% + \nopagebreak\ifhmode\\\fi% get into vertical mode + \nopagebreak\outputfootnotes{\arabic{\@mpfn}}% + \fi% +}% +% \end{macrocode} +% \DescribeMacro{\noentryfoot} +% This method simply suppresses footnotes at the end of the entry +% within the current group. This forces footnotes within the current +% group to be printed at the bottom of the page. +% +% This is useful in the case where \LaTeX\ expands the footnote at the +% end of the entry, then decides to put the page split between the +% footnote mark and the text. +% \begin{macrocode} +\newcommand{\noentryfoot}{\def\outputfootnotes@endgentry{}} +% \end{macrocode} +% \DescribeMacro{\outputfootnotes@endpage} +% This is called by the output routine at the end of each page. If +% \cs{botmark} has a value, then we can output all footnotes up to +% that index. +% \begin{macrocode} +\g@addto@macro{\gentry@footnotespergentry}{ +\newcommand{\outputfootnotes@endpage}{% + \expandafter\if\expandafter\relax\expandafter% + \detokenize\expandafter{\botmark}\relax\else% + \outputfootnotes{\botmark}% + \fi% +}}% +% \end{macrocode} +% \Finale +\endinput diff --git a/macros/latex/contrib/gamebooklib/gamebooklib.ins b/macros/latex/contrib/gamebooklib/gamebooklib.ins new file mode 100644 index 0000000000..843a747bbd --- /dev/null +++ b/macros/latex/contrib/gamebooklib/gamebooklib.ins @@ -0,0 +1,53 @@ +%% +%% Copyright (C) 2021 by Robert J Lee +%% +%% This file 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. +% +\input docstrip.tex +\keepsilent +\usedir{tex/latex/gamebooklib} +\preamble + +This is a generated file. + +Copyright (C) 2021 by Robert J Lee + +This file 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. + +\endpreamble + +\generate{\file{gamebooklib.sty}{\from{gamebooklib.dtx}{package}}} + +\obeyspaces + +\Msg{****************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the *} +\Msg{* following file into a directory searched by TeX: *} +\Msg{* *} +\Msg{* gamebooklib.sty *} +\Msg{* *} +\Msg{* To produce the documentation run the file *} +\Msg{* gamebooklib.dtx through LaTeX. *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{****************************************************} + +\endbatchfile diff --git a/macros/latex/contrib/gamebooklib/gamebooklib.pdf b/macros/latex/contrib/gamebooklib/gamebooklib.pdf new file mode 100644 index 0000000000..991b237de3 Binary files /dev/null and b/macros/latex/contrib/gamebooklib/gamebooklib.pdf differ diff --git a/macros/latex/contrib/gamebooklib/gamebooklib_countpagesperseed.sh b/macros/latex/contrib/gamebooklib/gamebooklib_countpagesperseed.sh new file mode 100755 index 0000000000..926e7d152e --- /dev/null +++ b/macros/latex/contrib/gamebooklib/gamebooklib_countpagesperseed.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# Copyright (C) 2021 by Robert J Lee +# +# This file 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. +# +# A utility script to find the best seed number for a particular gamebook +# +# Prerequisites: bash, tee, tail, egrep, pdflatex, perl with Sort::Naturally +# +# To install Sort::Naturally, you can simply type "cpan install Sort::Naturally" +# assuming Perl is installed. +# +# First keep a backup of your .tex file, just in case. +# +# Next, ensure that you have a line containing "seed=," +# (including the comma) in your .tex file. +# +# The first occurence will be replaced with a sequence of numbers in turn, +# the PDF regenerated, and the number of output pages with each number reported +# on, first by seed number, then by reversed number of pages (smallest last). +# It's then up to you to choose the seed number appropriate for your work. +# +# Use this script with caution as it will edit your source file. +# +# The script may be placed on the system path or copied to the working directory. + +file=${1} + +if [[ -z $file ]]; then + echo "Usage: $0 .tex" + exit 1 +fi + +egrep -q "seed=[0-9]+," $file || ( + echo "$1 Does not contain \\usepackage[seed=123,quiet]{lcg}" + exit 2 +); + +pdf="pdflatex -interaction=nonstopmode $file" + +cp $file $file~ || exit 3 + +# FOR seed in (1..1000) +for seed in $(perl -e 'for (1..1000){print "$_\n"}'); do + # edit $file and replace any seed values + perl -i -pe "s/seed=[0-9]*,/seed=$seed,/" $file + # Run it through LaTeX, stripping out the line of output containing the number of pages, and then + # add the seed value + echo $($pdf 2>&1 | grep 'pages' | tail -n 1 | perl -pe "chomp") "; seed=$seed"; +done | \ + # report on the output as we get it, and report on the sorted pages at the end. + # (sort numerically by first numeral on lines with identical prefix) + perl -MSort::Naturally -pe \ + '{push @lines, $_}; END{print "SORTED:"; print reverse nsort(@lines)}' diff --git a/macros/latex/contrib/gamebooklib/gamebooklib_test.pdf b/macros/latex/contrib/gamebooklib/gamebooklib_test.pdf new file mode 100644 index 0000000000..ceac9a9eb7 Binary files /dev/null and b/macros/latex/contrib/gamebooklib/gamebooklib_test.pdf differ diff --git a/macros/latex/contrib/gamebooklib/gamebooklib_test.tex b/macros/latex/contrib/gamebooklib/gamebooklib_test.tex new file mode 100644 index 0000000000..4d661dce63 --- /dev/null +++ b/macros/latex/contrib/gamebooklib/gamebooklib_test.tex @@ -0,0 +1,109 @@ +%% +%% This is file `gamebooklib_test.tex', +%% +%% Copyright (C) 2021 by Robert J Lee +%% +%% This file 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. +%% +\documentclass{report} +\usepackage[seed=123]{lcg} +\usepackage[verbose,footnote]{gamebooklib} +\usepackage{lipsum} +\begin{document} + +\newcommand{\turnto}[1]{\ref{gentry:#1}\par} + +\section*{Example of Use} + +This document was used for testing during development of gamebooklib. +Please see the \texttt{gamebooklib\_test.tex} file alongside the PDF +to see how the package behaves. + + +\begin{gentry}{codea} + This is the first gentry! + + It actually contains two gentryraphs. + +Turn to \turnto{codeb} +\end{gentry} + +\begin{gentry}{codea} + This one is a duplicate! This creates a `'multiple defined'' labels Warning! +\end{gentry} + +\begin{gentry}{codeb} + This is the second gentry. + + Turn to \turnto{codec} + +Turn to \turnto{coded} +\end{gentry} + +\begin{gentry}{codec}[You lose!] + This is the third gentry. + + You can't escape from here. +\end{gentry} + +\begin{gentry}[123]{coded}[You win!] + This is the second and final gentryraph. + + To play again, turn to \turnto{codea} + + (Note that this is the wrong number due to the duplicate label) +\end{gentry} + +\section*{Here is the result:} + +\thegentries +\eject + +For my next trick, here are some longer and multi-page examples. + +Note the location of the footnotes in these entries. + +\begin{gentry}{restart}\noentryfoot + This is the first gentryraph again. + \lipsum[1]\footnote{First footnote, forced to page end} +\end{gentry} + +\begin{gentry}{restart2} + \lipsum[2-7]\footnote{This is just Lorum Ipsum\footnote{Nonsense + pseudo-latin, with roughly English letter distribution, commonly + used to compare fonts\footnotemark.\footnotetext{Here, it's just nonsense.}}} +\end{gentry} + +\newcounter{foo} +\newcounter{bar} +\setcounter{foo}{3} +\setcounter{bar}{3} +\newcommand{\gentrytst}[2]{ + \begin{gentry}{restart#1} + \lipsum[#1]\footnote{This was gentry #1} + \lipsum[#1-#2]\footnote{This was also gentry #1} + \end{gentry} +} +\whiledo{\not{\value{foo}>10}}{ + \stepcounter{foo} + \stepcounter{bar} + \stepcounter{bar} + \edef\idx{\arabic{foo}} + \edef\idxx{\arabic{bar}} + \expandafter\gentrytst\expandafter{\idx}{\idxx} +} + +\section*{Here is the result:} + +\thegentries +\vfill + +\end{document} diff --git a/macros/latex/contrib/lambdax/lambdax.bib b/macros/latex/contrib/lambdax/lambdax.bib new file mode 100644 index 0000000000..62b85c380a --- /dev/null +++ b/macros/latex/contrib/lambdax/lambdax.bib @@ -0,0 +1,26 @@ +@misc{erw-ccool, + author = {Rogard, Erwann}, + title = {The \pkg{ccool} package for \LaTeX}, + note = {\url{https://github.com/rogard/ccool/blob/master/ccool.pdf}}, + year = {2020}} +@misc{erw-keyparse, + author = {Rogard, Erwann}, + title = {The \pkg{keyparse} package for \LaTeX}, + note = {\url{https://github.com/rogard/keyparse/blob/master/keyparse.pdf}}, + year = {2021}} +@manual{xparse, + title = {The \pkg{xparse} package}, + author = {The \LaTeX3 Project Team}, + year = {2019}, + note = {\url{https://ctan.math.illinois.edu/macros/latex/contrib/l3packages/xparse.pdf}}, + annote = {} } +@misc{a-188053, + author = {@{}sean-allred}, + title = {``How to create lambda expressions?''}, + year = {2014}, + note = {\url{https://tex.stackexchange.com/a/188053/112708}}} +@misc{q-610349, + author = {@{}Erwann}, + title = {``Troubleshooting \PrintIndex \PrintChanges''}, + year = {2021}, + note = {\url{https://tex.stackexchange.com/questions/610349/troubleshooting-printindex-printchanges}}} diff --git a/macros/latex/contrib/lambdax/lambdax.dtx b/macros/latex/contrib/lambdax/lambdax.dtx index 77e6a91115..36661218b8 100644 --- a/macros/latex/contrib/lambdax/lambdax.dtx +++ b/macros/latex/contrib/lambdax/lambdax.dtx @@ -69,11 +69,11 @@ lambdax.sty, and lambdax.pdf. % % \NeedsTeXFormat{LaTeX2e}[2021-06-01] % \RequirePackage{expl3, xparse, xtemplate, l3keys2e}[2021-06-01] -% \RequirePackage{lex}[2021-08-03] +% \RequirePackage{keyparse}[2021-08-18] % \ProvidesExplPackage % {lambdax} % Package name -% {2021-08-03} % Release date -% {1.0} % Release version +% {2021-08-18} % Release date +% {1.1} % Release version % {lambdax --- Lambda expression } % Description %<*driver> \documentclass[show-notes]{l3doc}%^^A full @@ -96,10 +96,10 @@ lambdax.sty, and lambdax.pdf. title = {The \pkg{ccool} package for \LaTeX}, note = {\url{https://github.com/rogard/ccool/blob/master/ccool.pdf}}, year = {2020}} -@misc{erw-lex, +@misc{erw-keyparse, author = {Rogard, Erwann}, - title = {The \pkg{lex} package for \LaTeX}, - note = {\url{https://github.com/rogard/lex/blob/master/lex.pdf}}, + title = {The \pkg{keyparse} package for \LaTeX}, + note = {\url{https://github.com/rogard/keyparse/blob/master/keyparse.pdf}}, year = {2021}} @manual{xparse, title = {The \pkg{xparse} package}, @@ -194,7 +194,7 @@ lambdax.sty, and lambdax.pdf. % \end{syntax} % \end{function} % \begin{descr} -% \item[Limitation] That of \pkg{lex}\cite{erw-lex}'s \texttt{argspec} collection. +% \item[Limitation] That of \pkg{keyparse}\cite{erw-keyparse}'s \texttt{argspec} collection. % \item[Argspec] Examples of \meta{bool-arg-type}\cite{xparse} and \meta{bool-arg} are |s| and |*|, respectively. % \item[Semantics] That of \cs{lambdax:nn} and recurse if applicable. % \end{descr} @@ -227,6 +227,9 @@ lambdax.sty, and lambdax.pdf. % \changes{Version 1.0} % {2020/08/03} % {Initial version} +% \changes{Version 1.1} +% {2020/08/18} +% {Dependency lex.sty renamed keyparse.sty} % \clearpage % \StopEventually{ % \PrintChanges @@ -338,7 +341,7 @@ lambdax.sty, and lambdax.pdf. % \begin{macrocode} \cs_new:Nn\@@_placeholder:n{#### #1} \cs_generate_variant:Nn\@@_placeholder:n{o,e} -\cs_new:Nn\@@_argspec:n{\lex_eval:nn{argspec}{#1}} +\cs_new:Nn\@@_argspec:n{\keyparse_eval:nn{argspec}{#1}} \cs_new:Nn\@@_argspec_count:n{\tl_count:e{\@@_argspec:n{#1}}} \cs_new:Nn\@@_chain_position:n{\int_eval:e{\@@_argspec_count:n{#1}+1}} \cs_new:Nn\@@_chain_placeholder:n diff --git a/macros/latex/contrib/lambdax/lambdax.pdf b/macros/latex/contrib/lambdax/lambdax.pdf new file mode 100644 index 0000000000..05c8c95f0f Binary files /dev/null and b/macros/latex/contrib/lambdax/lambdax.pdf differ diff --git a/macros/latex/contrib/projlib/ProjLib-doc-cn.pdf b/macros/latex/contrib/projlib/ProjLib-doc-cn.pdf index db10c276d5..dbadeb94d7 100644 Binary files a/macros/latex/contrib/projlib/ProjLib-doc-cn.pdf and b/macros/latex/contrib/projlib/ProjLib-doc-cn.pdf differ diff --git a/macros/latex/contrib/projlib/ProjLib-doc-en.pdf b/macros/latex/contrib/projlib/ProjLib-doc-en.pdf index 67f16164a8..f41e7621f7 100644 Binary files a/macros/latex/contrib/projlib/ProjLib-doc-en.pdf and b/macros/latex/contrib/projlib/ProjLib-doc-en.pdf differ diff --git a/macros/latex/contrib/projlib/ProjLib-doc-fr.pdf b/macros/latex/contrib/projlib/ProjLib-doc-fr.pdf index 18ae26be58..868b604e6a 100644 Binary files a/macros/latex/contrib/projlib/ProjLib-doc-fr.pdf and b/macros/latex/contrib/projlib/ProjLib-doc-fr.pdf differ diff --git a/macros/latex/contrib/projlib/ProjLib-doc.dtx b/macros/latex/contrib/projlib/ProjLib-doc.dtx index ac30792c0f..c5d10d507c 100644 --- a/macros/latex/contrib/projlib/ProjLib-doc.dtx +++ b/macros/latex/contrib/projlib/ProjLib-doc.dtx @@ -107,7 +107,7 @@ %<*ProjLib-doc-cn> \title{\ProjLib{} 工具集\\[.3\baselineskip]\normalsize 使用指南} \author{许锦文} -\thanks{对应版本.~~\texttt{\ProjLib{}~2021/08/17}} +\thanks{对应版本.~~\texttt{\ProjLib{}~2021/08/19}} \email{\href{mailto:ProjLib@outlook.com}{ProjLib@outlook.com}} \date{2021年8月,北京} % @@ -115,7 +115,7 @@ %<*ProjLib-doc-en> \title{\ProjLib{}~\,Toolkit\\[.3\baselineskip]\normalsize User Manual} \author{Jinwen XU} -\thanks{Corresponding to: \texttt{\ProjLib{}~2021/08/17}} +\thanks{Corresponding to: \texttt{\ProjLib{}~2021/08/19}} \email{\href{mailto:ProjLib@outlook.com}{ProjLib@outlook.com}} \date{August 2021, Beijing} % @@ -123,7 +123,7 @@ %<*ProjLib-doc-fr> \title{La boîte à outils~\,\ProjLib{}\\[.3\baselineskip]\normalsize Manuel d'utilisation} \author{Jinwen XU} -\thanks{Correspondant à : \texttt{\ProjLib{}~2021/08/17}} +\thanks{Correspondant à : \texttt{\ProjLib{}~2021/08/19}} \email{\href{mailto:ProjLib@outlook.com}{ProjLib@outlook.com}} \date{Août 2021, à Pékin} % diff --git a/macros/latex/contrib/projlib/ProjLib.dtx b/macros/latex/contrib/projlib/ProjLib.dtx index 7199d00910..fd3b252e1f 100644 --- a/macros/latex/contrib/projlib/ProjLib.dtx +++ b/macros/latex/contrib/projlib/ProjLib.dtx @@ -18,47 +18,47 @@ % %<*ProjLib> \ProvidesPackage{ProjLib} - [2021/08/17 The collective interface of ProjLib toolkit] + [2021/08/19 The collective interface of ProjLib toolkit] % % %<*PJLauthor> \ProvidesPackage{PJLauthor} - [2021/08/17 Enhanced author information block] + [2021/08/19 Enhanced author information block] % % %<*PJLdate> \ProvidesPackage{PJLdate} - [2021/08/17 Convert yyyy-mm-dd to normal datetime format] + [2021/08/19 Convert yyyy-mm-dd to normal datetime format] % % %<*PJLdraft> \ProvidesPackage{PJLdraft} - [2021/08/17 Some useful macros for the draft stage] + [2021/08/19 Some useful macros for the draft stage] % % %<*PJLlang> \ProvidesPackage{PJLlang} - [2021/08/17 Multi-language configuration] + [2021/08/19 Multi-language configuration] % % %<*PJLlogo> \ProvidesPackage{PJLlogo} - [2021/08/17 The ProjLib logo] + [2021/08/19 The ProjLib logo] % % %<*PJLmath> \ProvidesPackage{PJLmath} - [2021/08/17 Useful math macros and shortcuts] + [2021/08/19 Useful math macros and shortcuts] % % %<*PJLpaper> \ProvidesPackage{PJLpaper} - [2021/08/17 Paper style configuration] + [2021/08/19 Paper style configuration] % % %<*PJLthm> \ProvidesPackage{PJLthm} - [2021/08/17 Theorem setup and configuration] + [2021/08/19 Theorem setup and configuration] % % %# 下面两行引入宏包的代码是所有文件共用的。 @@ -1415,7 +1415,7 @@ \expandafter\IfEndWith\expandafter{\PJLthm@temp}{*}{% \expandafter\StrGobbleRight\expandafter{\PJLthm@temp}{1}[\PJLthm@temp]% }{}% - \IfSubStr{#3}{=}{% key-value mode + \IfSubStr{\detokenize{#3}}{=}{% key-value mode \IfValueTF{#1}{% \CreateTheoremSetKeys{\PJLthm@temp}{#1={#3}}% }{% @@ -2101,6 +2101,8 @@ \fi \CreateTheorem*{remark*} \CreateTheorem*{observation*} + +\theoremstyle{definition} \fi %# 按照 thmnum 决定公式如何编号 -- cgit v1.2.3