summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-09-16 03:01:00 +0000
committerNorbert Preining <norbert@preining.info>2023-09-16 03:01:00 +0000
commit659df224f4771e4390206a6663bcb78808d99767 (patch)
tree16bff62285b3a2dec0d2ca12822d819edc7ae3e6
parentdeda1937c52481b2259e1061840b99e18e8ca361 (diff)
CTAN sync 202309160300
-rw-r--r--FILES.byname176
-rw-r--r--FILES.byname.gzbin2549192 -> 2549201 bytes
-rw-r--r--FILES.last07days235
-rw-r--r--biblio/ctan-bibdata/ctan.bib14
-rw-r--r--biblio/ctan-bibdata/ctan.pdfbin3710053 -> 3708431 bytes
-rw-r--r--fonts/simpleicons/doc/simpleicons.pdfbin2186472 -> 2186651 bytes
-rw-r--r--fonts/simpleicons/opentype/SimpleIcons.otfbin2031168 -> 2031168 bytes
-rw-r--r--fonts/simpleicons/tex/simpleicons.sty2
-rw-r--r--fonts/simpleicons/tex/usimpleiconseight.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsfive.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsfour.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsnine.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsone.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsoneone.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsonezero.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsseven.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconssix.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconsthree.fd2
-rw-r--r--fonts/simpleicons/tex/usimpleiconstwo.fd2
-rw-r--r--fonts/simpleicons/type1/SimpleIcons.pfbbin1947818 -> 1947818 bytes
-rw-r--r--info/biblio/tugboat.bib69
-rw-r--r--info/biblio/tugboat.ltx16
-rw-r--r--macros/latex/contrib/robust-externalize/robust-externalize.pdfbin448699 -> 653662 bytes
-rw-r--r--macros/latex/contrib/robust-externalize/robust-externalize.sty1910
-rw-r--r--macros/latex/contrib/robust-externalize/robust-externalize.tex1733
-rw-r--r--systems/texlive/tlnet/tlpkg/TeXLive/TLPDB.pm27
-rw-r--r--systems/texlive/tlnet/tlpkg/TeXLive/TLUtils.pm77
-rw-r--r--systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl5
-rw-r--r--systems/texlive/tlnet/tlpkg/texlive.tlpdb62
-rw-r--r--systems/texlive/tlnet/tlpkg/texlive.tlpdb.md52
-rw-r--r--systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha5122
-rw-r--r--systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc16
-rw-r--r--systems/texlive/tlnet/tlpkg/texlive.tlpdb.xzbin2476204 -> 2473920 bytes
-rw-r--r--timestamp2
34 files changed, 3475 insertions, 895 deletions
diff --git a/FILES.byname b/FILES.byname
index 4dab002985..453c1041a7 100644
--- a/FILES.byname
+++ b/FILES.byname
@@ -2059,12 +2059,12 @@
2023/09/07 | 1710 | biblio/citation-style-language/README.md
2023/09/07 | 12878 | biblio/citation-style-language/vancouver.csl
2023/09/07 | 4530946 | biblio/citation-style-language.zip
-2023/09/14 | 1678 | biblio/ctan-bibdata/biblatex-ctan/ctan.bbx
+2023/09/15 | 1678 | biblio/ctan-bibdata/biblatex-ctan/ctan.bbx
2022/10/08 | 127 | biblio/ctan-bibdata/biblatex-ctan/ctan.cbx
-2023/09/14 | 2812990 | biblio/ctan-bibdata/ctan.bib
-2023/09/14 | 3710112 | biblio/ctan-bibdata/ctan.pdf
+2023/09/15 | 2812990 | biblio/ctan-bibdata/ctan.bib
+2023/09/15 | 3710053 | biblio/ctan-bibdata/ctan.pdf
2023/01/16 | 1489 | biblio/ctan-bibdata/README
-2023/09/14 | 4112043 | biblio/ctan-bibdata.zip
+2023/09/15 | 4112347 | biblio/ctan-bibdata.zip
2023/02/23 | 3126 | biblio/pbibtex/pbibtex-base/cpp.awk
2023/02/23 | 1009 | biblio/pbibtex/pbibtex-base/generate.sh
2023/02/23 | 22362 | biblio/pbibtex/pbibtex-base/jabbrv.bst
@@ -5424,7 +5424,7 @@
1990/10/02 | 5440 | dviware/vutex/vaxvms.hlp
1990/10/02 | 812 | dviware/vutex/vaxvms.ins
1990/10/02 | 127576 | dviware/vutex/vutex.web
-2023/09/14 | 260659 | FILES.last07days
+2023/09/15 | 132310 | FILES.last07days
2021/07/24 | 1139410 | fonts/aboensis/Aboensis.glyphs
2021/07/24 | 18907382 | fonts/aboensis/aboensis.pdf
2021/07/24 | 137860 | fonts/aboensis/Aboensis-Regular.otf
@@ -136236,50 +136236,50 @@
2008/10/27 | 1415 | fonts/shuffle/shuffle.mf
2008/10/27 | 295904 | fonts/shuffle/shuffle.pdf
2008/10/27 | 288258 | fonts/shuffle.zip
-2023/09/08 | 140214 | fonts/simpleicons/doc/bindings.tex
-2023/09/08 | 2186472 | fonts/simpleicons/doc/simpleicons.pdf
-2023/09/08 | 1844 | fonts/simpleicons/doc/simpleicons.tex
-2023/09/08 | 2562 | fonts/simpleicons/enc/simpleiconseight.enc
-2023/09/08 | 2425 | fonts/simpleicons/enc/simpleiconsfive.enc
-2023/09/08 | 2737 | fonts/simpleicons/enc/simpleiconsfour.enc
-2023/09/08 | 2708 | fonts/simpleicons/enc/simpleiconsnine.enc
-2023/09/08 | 2841 | fonts/simpleicons/enc/simpleiconsone.enc
-2023/09/08 | 2289 | fonts/simpleicons/enc/simpleiconsoneone.enc
-2023/09/08 | 2512 | fonts/simpleicons/enc/simpleiconsonezero.enc
-2023/09/08 | 2657 | fonts/simpleicons/enc/simpleiconsseven.enc
-2023/09/08 | 2670 | fonts/simpleicons/enc/simpleiconssix.enc
-2023/09/08 | 2540 | fonts/simpleicons/enc/simpleiconsthree.enc
-2023/09/08 | 2659 | fonts/simpleicons/enc/simpleiconstwo.enc
-2023/09/08 | 1236 | fonts/simpleicons/map/simpleicons.map
-2023/09/08 | 2031168 | fonts/simpleicons/opentype/SimpleIcons.otf
-2023/09/08 | 665 | fonts/simpleicons/README.md
-2023/09/08 | 236954 | fonts/simpleicons/tex/simpleiconsglyphs-pdftex.tex
-2023/09/08 | 231960 | fonts/simpleicons/tex/simpleiconsglyphs-xeluatex.tex
-2023/09/08 | 1521 | fonts/simpleicons/tex/simpleicons.sty
-2023/09/08 | 264 | fonts/simpleicons/tex/usimpleiconseight.fd
-2023/09/08 | 259 | fonts/simpleicons/tex/usimpleiconsfive.fd
-2023/09/08 | 259 | fonts/simpleicons/tex/usimpleiconsfour.fd
-2023/09/08 | 259 | fonts/simpleicons/tex/usimpleiconsnine.fd
-2023/09/08 | 254 | fonts/simpleicons/tex/usimpleiconsone.fd
-2023/09/08 | 269 | fonts/simpleicons/tex/usimpleiconsoneone.fd
-2023/09/08 | 274 | fonts/simpleicons/tex/usimpleiconsonezero.fd
-2023/09/08 | 264 | fonts/simpleicons/tex/usimpleiconsseven.fd
-2023/09/08 | 254 | fonts/simpleicons/tex/usimpleiconssix.fd
-2023/09/08 | 264 | fonts/simpleicons/tex/usimpleiconsthree.fd
-2023/09/08 | 254 | fonts/simpleicons/tex/usimpleiconstwo.fd
-2023/09/08 | 1236 | fonts/simpleicons/tfm/SimpleIcons--simpleiconseight.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfive.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfour.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsnine.tfm
-2023/09/08 | 492 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsoneone.tfm
-2023/09/08 | 1228 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsone.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsonezero.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsseven.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconssix.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsthree.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconstwo.tfm
-2023/09/08 | 1947818 | fonts/simpleicons/type1/SimpleIcons.pfb
-2023/09/08 | 5447062 | fonts/simpleicons.zip
+2023/09/15 | 140214 | fonts/simpleicons/doc/bindings.tex
+2023/09/15 | 2186651 | fonts/simpleicons/doc/simpleicons.pdf
+2023/09/15 | 1844 | fonts/simpleicons/doc/simpleicons.tex
+2023/09/15 | 2562 | fonts/simpleicons/enc/simpleiconseight.enc
+2023/09/15 | 2425 | fonts/simpleicons/enc/simpleiconsfive.enc
+2023/09/15 | 2737 | fonts/simpleicons/enc/simpleiconsfour.enc
+2023/09/15 | 2708 | fonts/simpleicons/enc/simpleiconsnine.enc
+2023/09/15 | 2841 | fonts/simpleicons/enc/simpleiconsone.enc
+2023/09/15 | 2289 | fonts/simpleicons/enc/simpleiconsoneone.enc
+2023/09/15 | 2512 | fonts/simpleicons/enc/simpleiconsonezero.enc
+2023/09/15 | 2657 | fonts/simpleicons/enc/simpleiconsseven.enc
+2023/09/15 | 2670 | fonts/simpleicons/enc/simpleiconssix.enc
+2023/09/15 | 2540 | fonts/simpleicons/enc/simpleiconsthree.enc
+2023/09/15 | 2659 | fonts/simpleicons/enc/simpleiconstwo.enc
+2023/09/15 | 1236 | fonts/simpleicons/map/simpleicons.map
+2023/09/15 | 2031168 | fonts/simpleicons/opentype/SimpleIcons.otf
+2023/09/15 | 665 | fonts/simpleicons/README.md
+2023/09/15 | 236954 | fonts/simpleicons/tex/simpleiconsglyphs-pdftex.tex
+2023/09/15 | 231960 | fonts/simpleicons/tex/simpleiconsglyphs-xeluatex.tex
+2023/09/15 | 1521 | fonts/simpleicons/tex/simpleicons.sty
+2023/09/15 | 264 | fonts/simpleicons/tex/usimpleiconseight.fd
+2023/09/15 | 259 | fonts/simpleicons/tex/usimpleiconsfive.fd
+2023/09/15 | 259 | fonts/simpleicons/tex/usimpleiconsfour.fd
+2023/09/15 | 259 | fonts/simpleicons/tex/usimpleiconsnine.fd
+2023/09/15 | 254 | fonts/simpleicons/tex/usimpleiconsone.fd
+2023/09/15 | 269 | fonts/simpleicons/tex/usimpleiconsoneone.fd
+2023/09/15 | 274 | fonts/simpleicons/tex/usimpleiconsonezero.fd
+2023/09/15 | 264 | fonts/simpleicons/tex/usimpleiconsseven.fd
+2023/09/15 | 254 | fonts/simpleicons/tex/usimpleiconssix.fd
+2023/09/15 | 264 | fonts/simpleicons/tex/usimpleiconsthree.fd
+2023/09/15 | 254 | fonts/simpleicons/tex/usimpleiconstwo.fd
+2023/09/15 | 1236 | fonts/simpleicons/tfm/SimpleIcons--simpleiconseight.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfive.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfour.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsnine.tfm
+2023/09/15 | 492 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsoneone.tfm
+2023/09/15 | 1228 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsone.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsonezero.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsseven.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconssix.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsthree.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconstwo.tfm
+2023/09/15 | 1947818 | fonts/simpleicons/type1/SimpleIcons.pfb
+2023/09/15 | 5447242 | fonts/simpleicons.zip
2002/02/27 | 3750 | fonts/skull/skull.dtx
2002/02/27 | 156 | fonts/skull/skull.ins
2002/02/27 | 2973 | fonts/skull/skull.mf
@@ -168002,9 +168002,9 @@
2019/12/12 | 3088 | info/biblio/texnique.ltx
1999/02/20 | 312 | info/biblio/tugbib2.ltx
1999/02/20 | 315 | info/biblio/tugbib.ltx
-2023/08/30 | 3923705 | info/biblio/tugboat.bib
+2023/09/14 | 3925319 | info/biblio/tugboat.bib
2023/02/28 | 9905 | info/biblio/tugboat.def
-2023/05/19 | 3574 | info/biblio/tugboat.ltx
+2023/09/14 | 3588 | info/biblio/tugboat.ltx
2014/08/12 | 20186 | info/biblio/type.bib
2019/12/12 | 2025 | info/biblio/type.ltx
2023/06/14 | 1197407 | info/biblio/typeset.bib
@@ -235865,11 +235865,11 @@
2006/04/04 | 1957 | macros/latex/contrib/robustcommand/robustcommand.ins
2006/04/11 | 72818 | macros/latex/contrib/robustcommand/robustcommand.pdf
2006/04/11 | 62251 | macros/latex/contrib/robustcommand.zip
-2023/09/06 | 463 | macros/latex/contrib/robust-externalize/README.md
-2023/09/06 | 448699 | macros/latex/contrib/robust-externalize/robust-externalize.pdf
-2023/09/06 | 55778 | macros/latex/contrib/robust-externalize/robust-externalize.sty
-2023/09/06 | 115037 | macros/latex/contrib/robust-externalize/robust-externalize.tex
-2023/09/06 | 438597 | macros/latex/contrib/robust-externalize.zip
+2023/09/15 | 463 | macros/latex/contrib/robust-externalize/README.md
+2023/09/15 | 653662 | macros/latex/contrib/robust-externalize/robust-externalize.pdf
+2023/09/15 | 120868 | macros/latex/contrib/robust-externalize/robust-externalize.sty
+2023/09/15 | 184959 | macros/latex/contrib/robust-externalize/robust-externalize.tex
+2023/09/15 | 643119 | macros/latex/contrib/robust-externalize.zip
2019/01/29 | 162849 | macros/latex/contrib/robustindex/multisample.pdf
2019/01/24 | 7898 | macros/latex/contrib/robustindex/multisample.tex
2019/01/29 | 1037 | macros/latex/contrib/robustindex/README.md
@@ -290871,9 +290871,9 @@
2019/02/28 | 27383316 | systems/texlive/tlnet/archive/arphic.r15878.tar.xz
2019/02/28 | 13072 | systems/texlive/tlnet/archive/arphic-ttf.doc.r42675.tar.xz
2019/02/28 | 12663696 | systems/texlive/tlnet/archive/arphic-ttf.r42675.tar.xz
-2023/08/10 | 464040 | systems/texlive/tlnet/archive/arraycols.doc.r67862.tar.xz
-2023/08/10 | 1320 | systems/texlive/tlnet/archive/arraycols.r67862.tar.xz
-2023/08/10 | 6752 | systems/texlive/tlnet/archive/arraycols.source.r67862.tar.xz
+2023/09/15 | 465540 | systems/texlive/tlnet/archive/arraycols.doc.r68277.tar.xz
+2023/09/15 | 1324 | systems/texlive/tlnet/archive/arraycols.r68277.tar.xz
+2023/09/15 | 6924 | systems/texlive/tlnet/archive/arraycols.source.r68277.tar.xz
2019/02/28 | 436304 | systems/texlive/tlnet/archive/arrayjobx.doc.r18125.tar.xz
2019/02/28 | 2976 | systems/texlive/tlnet/archive/arrayjobx.r18125.tar.xz
2019/02/28 | 302944 | systems/texlive/tlnet/archive/arraysort.doc.r31576.tar.xz
@@ -296560,8 +296560,8 @@
2022/07/26 | 63204 | systems/texlive/tlnet/archive/kfupm-math-exam.doc.r63977.tar.xz
2022/07/26 | 4120 | systems/texlive/tlnet/archive/kfupm-math-exam.r63977.tar.xz
2022/07/26 | 4852 | systems/texlive/tlnet/archive/kfupm-math-exam.source.r63977.tar.xz
-2023/09/13 | 313980 | systems/texlive/tlnet/archive/khatalmaqala.doc.r68250.tar.xz
-2023/09/13 | 664 | systems/texlive/tlnet/archive/khatalmaqala.r68250.tar.xz
+2023/09/15 | 79908 | systems/texlive/tlnet/archive/khatalmaqala.doc.r68280.tar.xz
+2023/09/15 | 234716 | systems/texlive/tlnet/archive/khatalmaqala.r68280.tar.xz
2021/12/24 | 1260 | systems/texlive/tlnet/archive/kinematikz.doc.r61392.tar.xz
2021/12/24 | 23308 | systems/texlive/tlnet/archive/kinematikz.r61392.tar.xz
2019/02/28 | 123796 | systems/texlive/tlnet/archive/kix.doc.r21606.tar.xz
@@ -296970,9 +296970,9 @@
2019/02/28 | 348 | systems/texlive/tlnet/archive/latexindent.x86_64-linuxmusl.r46840.tar.xz
2019/02/28 | 344 | systems/texlive/tlnet/archive/latexindent.x86_64-linux.r32150.tar.xz
2019/02/28 | 344 | systems/texlive/tlnet/archive/latexindent.x86_64-solaris.r32150.tar.xz
-2023/06/11 | 6809096 | systems/texlive/tlnet/archive/latex-lab-dev.doc.r67328.tar.xz
-2023/06/11 | 34252 | systems/texlive/tlnet/archive/latex-lab-dev.r67328.tar.xz
-2023/06/11 | 90844 | systems/texlive/tlnet/archive/latex-lab-dev.source.r67328.tar.xz
+2023/09/15 | 7098384 | systems/texlive/tlnet/archive/latex-lab-dev.doc.r68279.tar.xz
+2023/09/15 | 35128 | systems/texlive/tlnet/archive/latex-lab-dev.r68279.tar.xz
+2023/09/15 | 95832 | systems/texlive/tlnet/archive/latex-lab-dev.source.r68279.tar.xz
2023/06/09 | 6824276 | systems/texlive/tlnet/archive/latex-lab.doc.r67314.tar.xz
2023/06/09 | 34348 | systems/texlive/tlnet/archive/latex-lab.r67314.tar.xz
2023/06/09 | 90820 | systems/texlive/tlnet/archive/latex-lab.source.r67314.tar.xz
@@ -299281,8 +299281,8 @@
2019/02/28 | 134028 | systems/texlive/tlnet/archive/parselines.doc.r21475.tar.xz
2019/02/28 | 1872 | systems/texlive/tlnet/archive/parselines.r21475.tar.xz
2019/02/28 | 9128 | systems/texlive/tlnet/archive/parselines.source.r21475.tar.xz
-2023/09/14 | 94436 | systems/texlive/tlnet/archive/parsimatn.doc.r68271.tar.xz
-2023/09/14 | 122964 | systems/texlive/tlnet/archive/parsimatn.r68271.tar.xz
+2023/09/15 | 94384 | systems/texlive/tlnet/archive/parsimatn.doc.r68276.tar.xz
+2023/09/15 | 120404 | systems/texlive/tlnet/archive/parsimatn.r68276.tar.xz
2023/09/09 | 58516 | systems/texlive/tlnet/archive/parsinevis.doc.r68214.tar.xz
2023/09/09 | 131036 | systems/texlive/tlnet/archive/parsinevis.r68214.tar.xz
2021/03/15 | 312668 | systems/texlive/tlnet/archive/parskip.doc.r58358.tar.xz
@@ -302185,7 +302185,7 @@
2023/02/18 | 164944 | systems/texlive/tlnet/archive/tex.i386-solaris.r65877.tar.xz
2019/02/28 | 1956 | systems/texlive/tlnet/archive/texilikechaps.r28553.tar.xz
2019/02/28 | 956 | systems/texlive/tlnet/archive/texilikecover.r15878.tar.xz
-2023/08/18 | 97952 | systems/texlive/tlnet/archive/texinfo.r67954.tar.xz
+2023/09/15 | 98028 | systems/texlive/tlnet/archive/texinfo.r68275.tar.xz
2019/02/28 | 1336 | systems/texlive/tlnet/archive/tex-ini-files.doc.r40533.tar.xz
2019/02/28 | 3264 | systems/texlive/tlnet/archive/tex-ini-files.r40533.tar.xz
2019/02/28 | 36596 | systems/texlive/tlnet/archive/tex-label.doc.r16372.tar.xz
@@ -302250,7 +302250,7 @@
2022/09/13 | 600 | systems/texlive/tlnet/archive/texlive-scripts.amd64-freebsd.r64356.tar.xz
2022/09/13 | 596 | systems/texlive/tlnet/archive/texlive-scripts.amd64-netbsd.r64356.tar.xz
2022/09/13 | 596 | systems/texlive/tlnet/archive/texlive-scripts.armhf-linux.r64356.tar.xz
-2023/09/14 | 429632 | systems/texlive/tlnet/archive/texlive-scripts.doc.r68262.tar.xz
+2023/09/15 | 429652 | systems/texlive/tlnet/archive/texlive-scripts.doc.r68275.tar.xz
2020/01/27 | 916 | systems/texlive/tlnet/archive/texlive-scripts-extra.aarch64-linux.r53577.tar.xz
2020/01/27 | 924 | systems/texlive/tlnet/archive/texlive-scripts-extra.amd64-freebsd.r53577.tar.xz
2020/01/27 | 916 | systems/texlive/tlnet/archive/texlive-scripts-extra.amd64-netbsd.r53577.tar.xz
@@ -302272,7 +302272,7 @@
2022/09/13 | 592 | systems/texlive/tlnet/archive/texlive-scripts.i386-linux.r64356.tar.xz
2022/09/13 | 596 | systems/texlive/tlnet/archive/texlive-scripts.i386-netbsd.r64356.tar.xz
2022/09/13 | 596 | systems/texlive/tlnet/archive/texlive-scripts.i386-solaris.r64356.tar.xz
-2023/09/14 | 114132 | systems/texlive/tlnet/archive/texlive-scripts.r68262.tar.xz
+2023/09/15 | 114108 | systems/texlive/tlnet/archive/texlive-scripts.r68275.tar.xz
2022/09/13 | 580 | systems/texlive/tlnet/archive/texlive-scripts.universal-darwin.r64356.tar.xz
2023/05/14 | 60312 | systems/texlive/tlnet/archive/texlive-scripts.windows.r67095.tar.xz
2022/09/13 | 596 | systems/texlive/tlnet/archive/texlive-scripts.x86_64-cygwin.r64356.tar.xz
@@ -304129,9 +304129,9 @@
2023/08/16 | 1567496 | systems/texlive/tlnet/archive/zref-clever.doc.r67937.tar.xz
2023/08/16 | 23308 | systems/texlive/tlnet/archive/zref-clever.r67937.tar.xz
2023/08/16 | 52896 | systems/texlive/tlnet/archive/zref-clever.source.r67937.tar.xz
-2022/04/08 | 668676 | systems/texlive/tlnet/archive/zref.doc.r62977.tar.xz
-2022/04/08 | 14476 | systems/texlive/tlnet/archive/zref.r62977.tar.xz
-2022/04/08 | 37216 | systems/texlive/tlnet/archive/zref.source.r62977.tar.xz
+2023/09/15 | 668780 | systems/texlive/tlnet/archive/zref.doc.r68278.tar.xz
+2023/09/15 | 14528 | systems/texlive/tlnet/archive/zref.r68278.tar.xz
+2023/09/15 | 37528 | systems/texlive/tlnet/archive/zref.source.r68278.tar.xz
2023/08/17 | 781408 | systems/texlive/tlnet/archive/zref-vario.doc.r67949.tar.xz
2023/08/17 | 4536 | systems/texlive/tlnet/archive/zref-vario.r67949.tar.xz
2023/08/17 | 8112 | systems/texlive/tlnet/archive/zref-vario.source.r67949.tar.xz
@@ -304150,16 +304150,16 @@
2020/07/18 | 47816 | systems/texlive/tlnet/archive/zztex.doc.r55862.tar.xz
2020/07/18 | 101724 | systems/texlive/tlnet/archive/zztex.r55862.tar.xz
2023/08/07 | 125713 | systems/texlive/tlnet/install-tl
-2023/09/14 | 5742573 | systems/texlive/tlnet/install-tl-unx.tar.gz
-2023/09/14 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512
-2023/09/14 | 488 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc
+2023/09/15 | 5740348 | systems/texlive/tlnet/install-tl-unx.tar.gz
+2023/09/15 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512
+2023/09/15 | 488 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc
2023/05/13 | 5083 | systems/texlive/tlnet/install-tl-windows.bat
-2023/09/14 | 21037822 | systems/texlive/tlnet/install-tl-windows.exe
-2023/09/14 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512
-2023/09/14 | 488 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc
-2023/09/14 | 26028702 | systems/texlive/tlnet/install-tl.zip
-2023/09/14 | 145 | systems/texlive/tlnet/install-tl.zip.sha512
-2023/09/14 | 488 | systems/texlive/tlnet/install-tl.zip.sha512.asc
+2023/09/15 | 21037658 | systems/texlive/tlnet/install-tl-windows.exe
+2023/09/15 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512
+2023/09/15 | 488 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc
+2023/09/15 | 26028691 | systems/texlive/tlnet/install-tl.zip
+2023/09/15 | 145 | systems/texlive/tlnet/install-tl.zip.sha512
+2023/09/15 | 488 | systems/texlive/tlnet/install-tl.zip.sha512.asc
2023/03/19 | 1229 | systems/texlive/tlnet/README.md
2023/03/19 | 0 | systems/texlive/tlnet/TEXLIVE_2023
2023/01/17 | 8401 | systems/texlive/tlnet/tlpkg/gpg/pubring.gpg
@@ -304169,7 +304169,7 @@
2023/01/17 | 1280 | systems/texlive/tlnet/tlpkg/gpg/trustdb.gpg
2023/08/03 | 50576 | systems/texlive/tlnet/tlpkg/installer/config.guess
2010/11/11 | 11651 | systems/texlive/tlnet/tlpkg/installer/COPYING.MinGW-runtime.txt
-2023/09/13 | 7317 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl
+2023/09/14 | 7265 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl
2023/08/23 | 221470 | systems/texlive/tlnet/tlpkg/installer/curl/curl-ca-bundle.crt
2020/04/15 | 2606592 | systems/texlive/tlnet/tlpkg/installer/curl/curl.exe
2017/04/16 | 2629 | systems/texlive/tlnet/tlpkg/installer/installer-options.txt
@@ -304211,12 +304211,12 @@
2023/02/21 | 20371 | systems/texlive/tlnet/tlpkg/TeXLive/TLCrypto.pm
2021/12/21 | 5429 | systems/texlive/tlnet/tlpkg/TeXLive/TLDownload.pm
2023/04/08 | 28167 | systems/texlive/tlnet/tlpkg/TeXLive/TLPaper.pm
-2023/09/14 | 18259638 | systems/texlive/tlnet/tlpkg/texlive.tlpdb
-2023/09/14 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5
+2023/09/15 | 18259752 | systems/texlive/tlnet/tlpkg/texlive.tlpdb
+2023/09/15 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5
2023/02/20 | 86803 | systems/texlive/tlnet/tlpkg/TeXLive/TLPDB.pm
-2023/09/14 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512
-2023/09/14 | 488 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc
-2023/09/14 | 2475492 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz
+2023/09/15 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512
+2023/09/15 | 488 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc
+2023/09/15 | 2476204 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz
2023/02/20 | 58928 | systems/texlive/tlnet/tlpkg/TeXLive/TLPOBJ.pm
2023/06/11 | 42749 | systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm
2023/02/21 | 16138 | systems/texlive/tlnet/tlpkg/TeXLive/TLTREE.pm
@@ -314958,7 +314958,7 @@
2014/07/05 | 611 | systems/win32/yandy/README
2014/07/05 | 1004628 | systems/win32/yandy/yandy-src.tar.xz
2014/07/05 | 1012416 | systems/win32/yandy.zip
-2023/09/15 | 186 | timestamp
+2023/09/16 | 186 | timestamp
2002/08/26 | 61898 | usergrps/dante/antrag.pdf
2002/08/26 | 118217 | usergrps/dante/antrag.ps
2021/11/11 | 917 | usergrps/dante/dtk/doc/beispiel.bib
diff --git a/FILES.byname.gz b/FILES.byname.gz
index 75303fb38e..c2e7482530 100644
--- a/FILES.byname.gz
+++ b/FILES.byname.gz
Binary files differ
diff --git a/FILES.last07days b/FILES.last07days
index 45d8940b0c..0284908278 100644
--- a/FILES.last07days
+++ b/FILES.last07days
@@ -1,5 +1,87 @@
+2023/09/15 | 98028 | systems/texlive/tlnet/archive/texinfo.r68275.tar.xz
+2023/09/15 | 95832 | systems/texlive/tlnet/archive/latex-lab-dev.source.r68279.tar.xz
+2023/09/15 | 94384 | systems/texlive/tlnet/archive/parsimatn.doc.r68276.tar.xz
+2023/09/15 | 79908 | systems/texlive/tlnet/archive/khatalmaqala.doc.r68280.tar.xz
+2023/09/15 | 7098384 | systems/texlive/tlnet/archive/latex-lab-dev.doc.r68279.tar.xz
+2023/09/15 | 6924 | systems/texlive/tlnet/archive/arraycols.source.r68277.tar.xz
+2023/09/15 | 668780 | systems/texlive/tlnet/archive/zref.doc.r68278.tar.xz
+2023/09/15 | 665 | fonts/simpleicons/README.md
+2023/09/15 | 653662 | macros/latex/contrib/robust-externalize/robust-externalize.pdf
+2023/09/15 | 643119 | macros/latex/contrib/robust-externalize.zip
+2023/09/15 | 5740348 | systems/texlive/tlnet/install-tl-unx.tar.gz
+2023/09/15 | 5447242 | fonts/simpleicons.zip
+2023/09/15 | 492 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsoneone.tfm
+2023/09/15 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5
+2023/09/15 | 488 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc
+2023/09/15 | 488 | systems/texlive/tlnet/install-tl.zip.sha512.asc
+2023/09/15 | 488 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc
+2023/09/15 | 488 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc
+2023/09/15 | 465540 | systems/texlive/tlnet/archive/arraycols.doc.r68277.tar.xz
+2023/09/15 | 463 | macros/latex/contrib/robust-externalize/README.md
+2023/09/15 | 429652 | systems/texlive/tlnet/archive/texlive-scripts.doc.r68275.tar.xz
+2023/09/15 | 4112347 | biblio/ctan-bibdata.zip
+2023/09/15 | 37528 | systems/texlive/tlnet/archive/zref.source.r68278.tar.xz
+2023/09/15 | 3710053 | biblio/ctan-bibdata/ctan.pdf
+2023/09/15 | 35128 | systems/texlive/tlnet/archive/latex-lab-dev.r68279.tar.xz
+2023/09/15 | 2841 | fonts/simpleicons/enc/simpleiconsone.enc
+2023/09/15 | 2812990 | biblio/ctan-bibdata/ctan.bib
+2023/09/15 | 274 | fonts/simpleicons/tex/usimpleiconsonezero.fd
+2023/09/15 | 2737 | fonts/simpleicons/enc/simpleiconsfour.enc
+2023/09/15 | 2708 | fonts/simpleicons/enc/simpleiconsnine.enc
+2023/09/15 | 269 | fonts/simpleicons/tex/usimpleiconsoneone.fd
+2023/09/15 | 2670 | fonts/simpleicons/enc/simpleiconssix.enc
+2023/09/15 | 2659 | fonts/simpleicons/enc/simpleiconstwo.enc
+2023/09/15 | 2657 | fonts/simpleicons/enc/simpleiconsseven.enc
+2023/09/15 | 264 | fonts/simpleicons/tex/usimpleiconsthree.fd
+2023/09/15 | 264 | fonts/simpleicons/tex/usimpleiconsseven.fd
+2023/09/15 | 264 | fonts/simpleicons/tex/usimpleiconseight.fd
+2023/09/15 | 26028691 | systems/texlive/tlnet/install-tl.zip
+2023/09/15 | 259 | fonts/simpleicons/tex/usimpleiconsnine.fd
+2023/09/15 | 259 | fonts/simpleicons/tex/usimpleiconsfour.fd
+2023/09/15 | 259 | fonts/simpleicons/tex/usimpleiconsfive.fd
+2023/09/15 | 2562 | fonts/simpleicons/enc/simpleiconseight.enc
+2023/09/15 | 254 | fonts/simpleicons/tex/usimpleiconstwo.fd
+2023/09/15 | 254 | fonts/simpleicons/tex/usimpleiconssix.fd
+2023/09/15 | 254 | fonts/simpleicons/tex/usimpleiconsone.fd
+2023/09/15 | 2540 | fonts/simpleicons/enc/simpleiconsthree.enc
+2023/09/15 | 2512 | fonts/simpleicons/enc/simpleiconsonezero.enc
+2023/09/15 | 2476204 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz
+2023/09/15 | 2425 | fonts/simpleicons/enc/simpleiconsfive.enc
+2023/09/15 | 236954 | fonts/simpleicons/tex/simpleiconsglyphs-pdftex.tex
+2023/09/15 | 234716 | systems/texlive/tlnet/archive/khatalmaqala.r68280.tar.xz
+2023/09/15 | 231960 | fonts/simpleicons/tex/simpleiconsglyphs-xeluatex.tex
+2023/09/15 | 2289 | fonts/simpleicons/enc/simpleiconsoneone.enc
+2023/09/15 | 2186651 | fonts/simpleicons/doc/simpleicons.pdf
+2023/09/15 | 21037658 | systems/texlive/tlnet/install-tl-windows.exe
+2023/09/15 | 2031168 | fonts/simpleicons/opentype/SimpleIcons.otf
+2023/09/15 | 1947818 | fonts/simpleicons/type1/SimpleIcons.pfb
+2023/09/15 | 184959 | macros/latex/contrib/robust-externalize/robust-externalize.tex
+2023/09/15 | 1844 | fonts/simpleicons/doc/simpleicons.tex
+2023/09/15 | 18259752 | systems/texlive/tlnet/tlpkg/texlive.tlpdb
+2023/09/15 | 1678 | biblio/ctan-bibdata/biblatex-ctan/ctan.bbx
+2023/09/15 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512
+2023/09/15 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512
+2023/09/15 | 1521 | fonts/simpleicons/tex/simpleicons.sty
+2023/09/15 | 145 | systems/texlive/tlnet/install-tl.zip.sha512
+2023/09/15 | 14528 | systems/texlive/tlnet/archive/zref.r68278.tar.xz
+2023/09/15 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512
+2023/09/15 | 140214 | fonts/simpleicons/doc/bindings.tex
+2023/09/15 | 1324 | systems/texlive/tlnet/archive/arraycols.r68277.tar.xz
+2023/09/15 | 1236 | fonts/simpleicons/tfm/SimpleIcons--simpleiconseight.tfm
+2023/09/15 | 1236 | fonts/simpleicons/map/simpleicons.map
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconstwo.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsthree.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconssix.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsseven.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsonezero.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsnine.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfour.tfm
+2023/09/15 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfive.tfm
+2023/09/15 | 1228 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsone.tfm
+2023/09/15 | 120868 | macros/latex/contrib/robust-externalize/robust-externalize.sty
+2023/09/15 | 120404 | systems/texlive/tlnet/archive/parsimatn.r68276.tar.xz
+2023/09/15 | 114108 | systems/texlive/tlnet/archive/texlive-scripts.r68275.tar.xz
2023/09/14 | 9480 | fonts/utilities/fontools/bin/splitttc
-2023/09/14 | 94436 | systems/texlive/tlnet/archive/parsimatn.doc.r68271.tar.xz
2023/09/14 | 91880 | fonts/parsimatn/ParsiMatn-Italic.ttf
2023/09/14 | 91078 | fonts/parsimatn/parsimatn-example-of-use.pdf
2023/09/14 | 88940 | fonts/parsimatn/ParsiMatn-BoldItalic.ttf
@@ -15,6 +97,7 @@
2023/09/14 | 749456 | systems/texlive/tlnet/archive/latex-base-dev.source.r68270.tar.xz
2023/09/14 | 746672 | systems/texlive/tlnet/archive/l3build.doc.r68270.tar.xz
2023/09/14 | 74560 | systems/texlive/tlnet/archive/latexindent.r68268.tar.xz
+2023/09/14 | 7265 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl
2023/09/14 | 72654 | fonts/utilities/fontools/doc/autoinst.pdf
2023/09/14 | 707422 | macros/latex/contrib/zref.zip
2023/09/14 | 699604 | macros/latex/contrib/zref/zref.pdf
@@ -29,7 +112,6 @@
2023/09/14 | 5946 | macros/latex-dev/required/latex-lab/latex-lab.ins
2023/09/14 | 582 | macros/latex/contrib/zref/README.md
2023/09/14 | 5826 | macros/latex-dev/required/latex-lab/changes.txt
-2023/09/14 | 5742573 | systems/texlive/tlnet/install-tl-unx.tar.gz
2023/09/14 | 5733 | macros/latex-dev/required/latex-lab/latex-lab-toc-hyperref-changes.dtx
2023/09/14 | 5684 | macros/latex-dev/required/latex-lab/latex-lab-new-or-1.dtx
2023/09/14 | 5468 | fonts/utilities/fontools/share/fontools_t3.enc
@@ -37,11 +119,6 @@
2023/09/14 | 528176 | macros/latex-dev/required/latex-lab/latex-lab-sec.pdf
2023/09/14 | 523606 | macros/latex-dev/required/latex-lab/documentmetadata-support-code.pdf
2023/09/14 | 497260 | macros/latex-dev/required/latex-lab/latex-lab-graphic.pdf
-2023/09/14 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5
-2023/09/14 | 488 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc
-2023/09/14 | 488 | systems/texlive/tlnet/install-tl.zip.sha512.asc
-2023/09/14 | 488 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc
-2023/09/14 | 488 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc
2023/09/14 | 4770 | macros/latex-dev/required/latex-lab/latex-lab-testphase.dtx
2023/09/14 | 476 | systems/texlive/tlnet/archive/collection-langarabic.r68271.tar.xz
2023/09/14 | 4753336 | systems/texlive/tlnet/archive/latexindent.windows.r68268.tar.xz
@@ -50,20 +127,19 @@
2023/09/14 | 444989 | macros/latex-dev/required/latex-lab/latex-lab-float.pdf
2023/09/14 | 440245 | macros/latex-dev/required/latex-lab/blocks-doc.pdf
2023/09/14 | 4364 | fonts/utilities/fontools/share/fontools_t2b.enc
-2023/09/14 | 429632 | systems/texlive/tlnet/archive/texlive-scripts.doc.r68262.tar.xz
2023/09/14 | 4286 | fonts/utilities/fontools/share/fontools_t2c.enc
-2023/09/14 | 4112043 | biblio/ctan-bibdata.zip
2023/09/14 | 411100 | macros/latex-dev/required/latex-lab/latex-lab-bib.pdf
+2023/09/14 | 3925319 | info/biblio/tugboat.bib
2023/09/14 | 389733 | macros/latex-dev/required/latex-lab/latex-lab-new-or-1.pdf
2023/09/14 | 389235 | macros/latex-dev/required/latex-lab/documentmetadata-support-doc.pdf
2023/09/14 | 3844 | fonts/utilities/fontools/share/fontools_t5.enc
2023/09/14 | 377490 | macros/latex-dev/required/latex-lab/latex-lab-toc.pdf
-2023/09/14 | 3710112 | biblio/ctan-bibdata/ctan.pdf
2023/09/14 | 36968 | macros/latex-dev/required/latex-lab/latex-lab-math.dtx
2023/09/14 | 3669 | macros/latex-dev/required/latex-lab/latex-lab-text.dtx
2023/09/14 | 3664 | fonts/utilities/fontools/share/fontools_t4.enc
2023/09/14 | 36544 | systems/texlive/tlnet/archive/l3build.r68270.tar.xz
2023/09/14 | 3592 | fonts/utilities/fontools/share/fontools_ts1.enc
+2023/09/14 | 3588 | info/biblio/tugboat.ltx
2023/09/14 | 357811 | macros/latex-dev/required/latex-lab/latex-lab-mathtools.pdf
2023/09/14 | 357811 | macros/latex-dev/required/latex-lab/latex-lab-amsmath.pdf
2023/09/14 | 356743 | macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.pdf
@@ -92,16 +168,13 @@
2023/09/14 | 291894 | fonts/parsimatn.zip
2023/09/14 | 2882 | macros/latex-dev/required/latex-lab/latex-lab-namespace.dtx
2023/09/14 | 2880 | systems/texlive/tlnet/archive/latex-firstaid-dev.r68270.tar.xz
-2023/09/14 | 2812990 | biblio/ctan-bibdata/ctan.bib
2023/09/14 | 278305 | macros/latex-dev/required/latex-lab/latex-lab-minipage.pdf
2023/09/14 | 27582 | fonts/utilities/fontools/bin/ot2kpx
2023/09/14 | 27320 | fonts/utilities/fontools/doc/ot2kpx.pdf
2023/09/14 | 272876 | macros/latex-dev/required/latex-lab/latex-lab-firstaid.pdf
2023/09/14 | 27043 | macros/latex-dev/required/latex-lab/latex-lab-sec.dtx
2023/09/14 | 26954 | fonts/utilities/fontools/doc/afm2afm.pdf
-2023/09/14 | 26028702 | systems/texlive/tlnet/install-tl.zip
2023/09/14 | 2528 | systems/texlive/tlnet/archive/runtexshebang.doc.r68269.tar.xz
-2023/09/14 | 2475492 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz
2023/09/14 | 247104 | systems/texlive/tlnet/archive/latex-firstaid-dev.doc.r68270.tar.xz
2023/09/14 | 2453 | macros/latex-dev/required/latex-lab/latex-lab-mathpkg.dtx
2023/09/14 | 2420584 | systems/texlive/tlnet/archive/latex-amsmath-dev.doc.r68270.tar.xz
@@ -110,36 +183,27 @@
2023/09/14 | 234661 | macros/latex-dev/required/latex-lab/latex-lab-namespace.pdf
2023/09/14 | 220535 | fonts/utilities/fontools.zip
2023/09/14 | 2180 | systems/texlive/tlnet/archive/runtexshebang.r68269.tar.xz
-2023/09/14 | 21037822 | systems/texlive/tlnet/install-tl-windows.exe
2023/09/14 | 20437 | fonts/utilities/fontools/doc/splitttc.pdf
2023/09/14 | 198236 | macros/latex/contrib/zref/zref.dtx
2023/09/14 | 19447 | macros/latex-dev/required/latex-lab/documentmetadata-support.dtx
2023/09/14 | 191 | macros/latex-dev/required/latex-lab/documentmetadata-support-doc.tex
-2023/09/14 | 18259638 | systems/texlive/tlnet/tlpkg/texlive.tlpdb
2023/09/14 | 18202 | CTAN.sites
2023/09/14 | 17997 | fonts/utilities/fontools/GPLv2.txt
2023/09/14 | 17593 | macros/latex-dev/required/latex-lab/latex-lab-toc-kernel-changes.dtx
2023/09/14 | 175638 | fonts/utilities/fontools/bin/autoinst
2023/09/14 | 17241 | fonts/utilities/fontools/share/fontools_lgr.enc
2023/09/14 | 16852 | macros/latex-dev/required/latex-lab/latex-lab-float.dtx
-2023/09/14 | 1678 | biblio/ctan-bibdata/biblatex-ctan/ctan.bbx
2023/09/14 | 1573108 | systems/texlive/tlnet/archive/inconsolata-nerd-font.r68263.tar.xz
-2023/09/14 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512
-2023/09/14 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512
2023/09/14 | 1500 | systems/texlive/tlnet/archive/circuit-macros.r68264.tar.xz
-2023/09/14 | 145 | systems/texlive/tlnet/install-tl.zip.sha512
-2023/09/14 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512
2023/09/14 | 14027 | macros/latex-dev/required/latex-lab/latex-lab-bib.dtx
2023/09/14 | 135159 | macros/latex-dev/required/latex-lab/latex-lab-block.dtx
2023/09/14 | 1335380 | systems/texlive/tlnet/archive/latexindent.doc.r68268.tar.xz
2023/09/14 | 13334 | fonts/utilities/fontools/bin/afm2afm
2023/09/14 | 1320736 | systems/texlive/tlnet/archive/inconsolata-nerd-font.doc.r68263.tar.xz
2023/09/14 | 12840 | systems/texlive/tlnet/archive/lua-typo.r68267.tar.xz
-2023/09/14 | 122964 | systems/texlive/tlnet/archive/parsimatn.r68271.tar.xz
2023/09/14 | 117 | macros/latex-dev/required/latex-lab/documentmetadata-support-code.tex
2023/09/14 | 11652 | macros/latex-dev/required/latex-lab/latex-lab-toc.dtx
2023/09/14 | 1156 | macros/latex-dev/required/latex-lab/README.md
-2023/09/14 | 114132 | systems/texlive/tlnet/archive/texlive-scripts.r68262.tar.xz
2023/09/14 | 108 | macros/latex-dev/required/latex-lab/blocks-code.tex
2023/09/14 | 10803422 | install/macros/latex-dev/required/latex-lab-dev.tds.zip
2023/09/14 | 10726234 | macros/latex-dev/required/latex-lab.zip
@@ -198,7 +262,6 @@
2023/09/13 | 744760 | macros/latex/contrib/l3build/l3build.pdf
2023/09/13 | 7445 | support/latexindent/LatexIndent/BackUpFileProcedure.pm
2023/09/13 | 7379 | support/latexindent/LatexIndent/MandatoryArgument.pm
-2023/09/13 | 7317 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl
2023/09/13 | 72475 | macros/latex-dev/base/ltfsstrc.dtx
2023/09/13 | 7244 | macros/latex-dev/base/ltnews20.tex
2023/09/13 | 7216 | macros/latex-dev/base/exscale.dtx
@@ -222,7 +285,6 @@
2023/09/13 | 672682 | macros/latex-dev/base/ltpara-code.pdf
2023/09/13 | 6709 | macros/latex-dev/base/latexsym.dtx
2023/09/13 | 6664 | support/latexindent/documentation/contributors.bib
-2023/09/13 | 664 | systems/texlive/tlnet/archive/khatalmaqala.r68250.tar.xz
2023/09/13 | 6620 | support/latexindent/LatexIndent/OptionalArgument.pm
2023/09/13 | 65684 | macros/latex-dev/base/ltmiscen.dtx
2023/09/13 | 6440 | macros/latex-dev/required/amsmath/subeqn.tex
@@ -400,7 +462,6 @@
2023/09/13 | 318199 | macros/latex-dev/base/inputenc.pdf
2023/09/13 | 318193 | macros/latex-dev/base/ltnews20.pdf
2023/09/13 | 318026 | macros/latex-dev/base/ltnews22.pdf
-2023/09/13 | 313980 | systems/texlive/tlnet/archive/khatalmaqala.doc.r68250.tar.xz
2023/09/13 | 3100 | macros/latex-dev/base/README.md
2023/09/13 | 30499 | macros/latex-dev/base/doc-2021-06-01.sty
2023/09/13 | 30452 | macros/latex-dev/base/ltnews31.tex
@@ -1676,127 +1737,3 @@
2023/09/09 | 1068 | systems/texlive/tlnet/archive/curriculum-vitae.r68211.tar.xz
2023/09/09 | 106197 | macros/latex/contrib/ucph-revy/ucph-revy.dtx
2023/09/09 | 102456 | systems/texlive/tlnet/archive/curriculum-vitae.doc.r68211.tar.xz
-2023/09/08 | 99268 | fonts/parsinevis/ParsiNevis-Italic.ttf
-2023/09/08 | 94352 | macros/latex/contrib/ppt-slides/socrates.jpg
-2023/09/08 | 93510 | graphics/pstricks/contrib/pst-3dplot/tex/pst-3dplot.tex
-2023/09/08 | 932902 | macros/latex/contrib/ppt-slides/ppt-slides.pdf
-2023/09/08 | 90716 | fonts/parsinevis/ParsiNevis-Bold.ttf
-2023/09/08 | 88137 | graphics/pstricks/contrib/pst-3dplot/doc/pst-3dplot-doc.tex
-2023/09/08 | 87552 | fonts/parsinevis/ParsiNevis-Regular.ttf
-2023/09/08 | 80 | macros/latex/contrib/runcode/generated/runcode_troubleshoot_inln8.tex
-2023/09/08 | 80 | macros/latex/contrib/runcode/generated/runcode_troubleshoot_inln7.tex
-2023/09/08 | 710 | fonts/parsinevis/parsinevis-sample.tex
-2023/09/08 | 671 | fonts/parsinevis/README.md
-2023/09/08 | 669 | graphics/pstricks/contrib/pst-3dplot/README
-2023/09/08 | 665 | fonts/simpleicons/README.md
-2023/09/08 | 6590 | graphics/pstricks/contrib/pst-3dplot/Changes
-2023/09/08 | 642 | macros/latex/contrib/ppt-slides/DEPENDS.txt
-2023/09/08 | 629 | macros/latex/contrib/musicography/README.md
-2023/09/08 | 60 | macros/latex/contrib/runcode/generated/runcode_troubleshoot_inln2.tex
-2023/09/08 | 5692 | systems/texlive/tlnet/archive/odsfile.r68204.tar.xz
-2023/09/08 | 56114 | fonts/parsinevis/parsinevis-sample.pdf
-2023/09/08 | 554 | macros/latex/contrib/runcode/generated/testWithrunR.tex
-2023/09/08 | 551 | graphics/pstricks/contrib/pst-3dplot/latex/pst-3dplot.sty
-2023/09/08 | 5447062 | fonts/simpleicons.zip
-2023/09/08 | 4 | macros/latex/contrib/runcode/generated/runcode_troubleshoot_inln6.tex
-2023/09/08 | 492 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsoneone.tfm
-2023/09/08 | 469960 | systems/texlive/tlnet/archive/marginnote.doc.r68204.tar.xz
-2023/09/08 | 4498 | fonts/parsinevis/OFL.txt
-2023/09/08 | 43092 | systems/texlive/tlnet/archive/suftesi.source.r68204.tar.xz
-2023/09/08 | 4137 | graphics/pstricks/contrib/pst-3dplot/doc/pst-3dplot-doc.bib
-2023/09/08 | 408052 | macros/latex/contrib/musicography/musicography.pdf
-2023/09/08 | 407424 | macros/latex/contrib/musicography.zip
-2023/09/08 | 3989 | macros/latex/contrib/ppt-slides/ppt-templates/ppt-9x6.tex
-2023/09/08 | 391 | fonts/firamath-otf/README.md
-2023/09/08 | 376 | systems/texlive/tlnet/archive/lshort-slovenian.r68204.tar.xz
-2023/09/08 | 3364 | systems/texlive/tlnet/archive/korigamik.r68204.tar.xz
-2023/09/08 | 3312 | systems/texlive/tlnet/archive/marginnote.r68204.tar.xz
-2023/09/08 | 32822 | fonts/firamath-otf/doc/firamath-otf-doc.tex
-2023/09/08 | 3033906 | graphics/pstricks/contrib/pst-3dplot/doc/pst-3dplot-doc.pdf
-2023/09/08 | 293 | fonts/firamath-otf/Changes
-2023/09/08 | 2914 | fonts/firamath-otf/latex/firamath-otf.sty
-2023/09/08 | 2843326 | graphics/pstricks/contrib/pst-3dplot.zip
-2023/09/08 | 2841 | fonts/simpleicons/enc/simpleiconsone.enc
-2023/09/08 | 2817588 | systems/texlive/tlnet/archive/citation-style-language.r68204.tar.xz
-2023/09/08 | 274 | fonts/simpleicons/tex/usimpleiconsonezero.fd
-2023/09/08 | 2737 | fonts/simpleicons/enc/simpleiconsfour.enc
-2023/09/08 | 2708 | fonts/simpleicons/enc/simpleiconsnine.enc
-2023/09/08 | 269 | fonts/simpleicons/tex/usimpleiconsoneone.fd
-2023/09/08 | 2670 | fonts/simpleicons/enc/simpleiconssix.enc
-2023/09/08 | 2659 | fonts/simpleicons/enc/simpleiconstwo.enc
-2023/09/08 | 2657 | fonts/simpleicons/enc/simpleiconsseven.enc
-2023/09/08 | 264 | fonts/simpleicons/tex/usimpleiconsthree.fd
-2023/09/08 | 264 | fonts/simpleicons/tex/usimpleiconsseven.fd
-2023/09/08 | 264 | fonts/simpleicons/tex/usimpleiconseight.fd
-2023/09/08 | 26449 | graphics/pstricks/contrib/pst-3dplot/doc/pst-3dplot-doc.dat
-2023/09/08 | 2640 | macros/latex/contrib/ppt-slides/ppt-slides.ins
-2023/09/08 | 25 | macros/latex/contrib/runcode/generated/runcode_troubleshoot_inln5.tex
-2023/09/08 | 25 | macros/latex/contrib/runcode/generated/runcode_troubleshoot_inln4.tex
-2023/09/08 | 259 | fonts/simpleicons/tex/usimpleiconsnine.fd
-2023/09/08 | 259 | fonts/simpleicons/tex/usimpleiconsfour.fd
-2023/09/08 | 259 | fonts/simpleicons/tex/usimpleiconsfive.fd
-2023/09/08 | 2562 | fonts/simpleicons/enc/simpleiconseight.enc
-2023/09/08 | 254 | fonts/simpleicons/tex/usimpleiconstwo.fd
-2023/09/08 | 254 | fonts/simpleicons/tex/usimpleiconssix.fd
-2023/09/08 | 254 | fonts/simpleicons/tex/usimpleiconsone.fd
-2023/09/08 | 2540 | fonts/simpleicons/enc/simpleiconsthree.enc
-2023/09/08 | 251374 | macros/latex/contrib/runcode/runcode.pdf
-2023/09/08 | 2512 | fonts/simpleicons/enc/simpleiconsonezero.enc
-2023/09/08 | 2496 | macros/latex/contrib/ucph-revy/README.md
-2023/09/08 | 247528 | systems/texlive/tlnet/archive/citation-style-language.doc.r68204.tar.xz
-2023/09/08 | 242787 | fonts/parsinevis.zip
-2023/09/08 | 2425 | fonts/simpleicons/enc/simpleiconsfive.enc
-2023/09/08 | 236954 | fonts/simpleicons/tex/simpleiconsglyphs-pdftex.tex
-2023/09/08 | 231960 | fonts/simpleicons/tex/simpleiconsglyphs-xeluatex.tex
-2023/09/08 | 2289 | fonts/simpleicons/enc/simpleiconsoneone.enc
-2023/09/08 | 2186472 | fonts/simpleicons/doc/simpleicons.pdf
-2023/09/08 | 2031168 | fonts/simpleicons/opentype/SimpleIcons.otf
-2023/09/08 | 1947818 | fonts/simpleicons/type1/SimpleIcons.pfb
-2023/09/08 | 19096 | macros/latex/contrib/runcode/runcode.sty
-2023/09/08 | 18978 | macros/latex/contrib/runcode/runcode_troubleshoot.tex
-2023/09/08 | 18726 | macros/latex/contrib/ppt-slides/ppt-slides.dtx
-2023/09/08 | 1844 | fonts/simpleicons/doc/simpleicons.tex
-2023/09/08 | 16824 | macros/latex/contrib/runcode/runcode.tex
-2023/09/08 | 1620 | macros/latex/contrib/ppt-slides/README.md
-2023/09/08 | 161688 | macros/latex/contrib/runcode/runcode_troubleshoot.pdf
-2023/09/08 | 1521 | fonts/simpleicons/tex/simpleicons.sty
-2023/09/08 | 14808 | systems/texlive/tlnet/archive/suftesi.r68204.tar.xz
-2023/09/08 | 1449 | macros/latex/contrib/runcode/README
-2023/09/08 | 1420 | macros/latex/contrib/ppt-slides/ppt-schemes/ppt-light.tex
-2023/09/08 | 1420 | macros/latex/contrib/ppt-slides/ppt-schemes/ppt-light-mono.tex
-2023/09/08 | 1420 | macros/latex/contrib/ppt-slides/ppt-schemes/ppt-dark.tex
-2023/09/08 | 1420 | macros/latex/contrib/ppt-slides/ppt-schemes/ppt-dark-mono.tex
-2023/09/08 | 14157972 | systems/texlive/tlnet/archive/profcollege.doc.r68204.tar.xz
-2023/09/08 | 14151 | macros/latex/contrib/musicography/musicography.sty
-2023/09/08 | 140214 | fonts/simpleicons/doc/bindings.tex
-2023/09/08 | 139390 | graphics/metapost/contrib/macros/wordcloud.zip
-2023/09/08 | 1390728 | systems/texlive/tlnet/archive/lshort-slovenian.doc.r68204.tar.xz
-2023/09/08 | 1369 | macros/latex/contrib/ucph-revy/ucph-revy-da-doc.ins
-2023/09/08 | 1329 | macros/latex/contrib/ucph-revy/ucph-revy-en-doc.ins
-2023/09/08 | 1311544 | systems/texlive/tlnet/archive/profcollege.r68204.tar.xz
-2023/09/08 | 12 | macros/latex/contrib/runcode/generated/runcode_troubleshoot_inln9.tex
-2023/09/08 | 1287 | macros/latex/contrib/ucph-revy/ucph-revy-da-man.ins
-2023/09/08 | 1270 | macros/latex/contrib/ucph-revy/ucph-revy-en-man.ins
-2023/09/08 | 125869 | fonts/firamath-otf.zip
-2023/09/08 | 12559 | macros/latex/contrib/musicography/musicography.tex
-2023/09/08 | 1236 | fonts/simpleicons/tfm/SimpleIcons--simpleiconseight.tfm
-2023/09/08 | 1236 | fonts/simpleicons/map/simpleicons.map
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconstwo.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsthree.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconssix.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsseven.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsonezero.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsnine.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfour.tfm
-2023/09/08 | 1232 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsfive.tfm
-2023/09/08 | 1228 | fonts/simpleicons/tfm/SimpleIcons--simpleiconsone.tfm
-2023/09/08 | 122504 | systems/texlive/tlnet/archive/korigamik.doc.r68204.tar.xz
-2023/09/08 | 120980 | fonts/firamath-otf/doc/firamath-otf-doc.pdf
-2023/09/08 | 110928 | systems/texlive/tlnet/archive/odsfile.doc.r68204.tar.xz
-2023/09/08 | 1083 | macros/latex/contrib/ppt-slides/LICENSE.txt
-2023/09/08 | 10759 | graphics/pgf/contrib/tkz-bernoulli/tex/tkz-bernoulli.sty
-2023/09/08 | 1040744 | systems/texlive/tlnet/archive/suftesi.doc.r68204.tar.xz
-2023/09/08 | 102583 | macros/latex/contrib/curriculum-vitae.zip
-2023/09/08 | 102236 | fonts/parsinevis/ParsiNevis-BoldItalic.ttf
-2023/09/08 | 10208 | systems/texlive/tlnet/archive/marginnote.source.r68204.tar.xz
-2023/09/08 | 1019134 | macros/latex/contrib/ppt-slides.zip
diff --git a/biblio/ctan-bibdata/ctan.bib b/biblio/ctan-bibdata/ctan.bib
index 6f3bed7ca2..6c3eab5a75 100644
--- a/biblio/ctan-bibdata/ctan.bib
+++ b/biblio/ctan-bibdata/ctan.bib
@@ -1,7 +1,7 @@
%% bib file of all CTAN packages
%% (C) Herbert Voß
%%
-%% created at 15-09-2023, 02:00:13
+%% created at 16-09-2023, 02:03:11
%%
%% This file is provided under the terms of the LPPL v1.3 or
@@ -45671,9 +45671,9 @@
@manual{ctan-mitthesis,
title = {The \texttt{mitthesis} package},
- subtitle = {A \LaTeX{} template for MIT theses},
+ subtitle = {A \LaTeX{} template for an MIT thesis},
author = {John H. Lienhard},
- date = {2023-09-12},
+ date = {2023-09-15},
version = {1.08},
license = {mit},
mirror = {https://mirror.ctan.org/macros/latex/contrib/mitthesis},
@@ -59397,8 +59397,8 @@
title = {The \texttt{robust-externalize} package},
subtitle = {Cache anything (TikZ, python, ...) in a robust, efficient and pure way},
author = {Léo Colisson},
- date = {2023-09-11},
- version = {1.0},
+ date = {2023-09-15},
+ version = {2.0},
license = {mit},
mirror = {https://mirror.ctan.org/macros/latex/contrib/robust-externalize},
url = {https://ctan.org/pkg/robust-externalize},
@@ -62709,8 +62709,8 @@
title = {The \texttt{simpleicons} package},
subtitle = {Simple Icons for \LaTeX{}},
author = {Inesh Bose},
- date = {2023-09-08},
- version = {9.13.0},
+ date = {2023-09-15},
+ version = {9.14.0},
license = {cc-by-1},
mirror = {https://mirror.ctan.org/fonts/simpleicons},
url = {https://ctan.org/pkg/simpleicons},
diff --git a/biblio/ctan-bibdata/ctan.pdf b/biblio/ctan-bibdata/ctan.pdf
index ef3ea05e26..c683e78579 100644
--- a/biblio/ctan-bibdata/ctan.pdf
+++ b/biblio/ctan-bibdata/ctan.pdf
Binary files differ
diff --git a/fonts/simpleicons/doc/simpleicons.pdf b/fonts/simpleicons/doc/simpleicons.pdf
index 77c9a9194e..b518d18889 100644
--- a/fonts/simpleicons/doc/simpleicons.pdf
+++ b/fonts/simpleicons/doc/simpleicons.pdf
Binary files differ
diff --git a/fonts/simpleicons/opentype/SimpleIcons.otf b/fonts/simpleicons/opentype/SimpleIcons.otf
index 4d23ffbcc4..d5e8c798ae 100644
--- a/fonts/simpleicons/opentype/SimpleIcons.otf
+++ b/fonts/simpleicons/opentype/SimpleIcons.otf
Binary files differ
diff --git a/fonts/simpleicons/tex/simpleicons.sty b/fonts/simpleicons/tex/simpleicons.sty
index 8c82e6361b..f5bfcc28c3 100644
--- a/fonts/simpleicons/tex/simpleicons.sty
+++ b/fonts/simpleicons/tex/simpleicons.sty
@@ -1,6 +1,6 @@
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{simpleicons}[2023/09/08 9.13.0 Simple Icons 9.10.0 Logos]
+\ProvidesPackage{simpleicons}[2023/09/15 9.14.0 Simple Icons 9.10.0 Logos]
\RequirePackage{iftex}
diff --git a/fonts/simpleicons/tex/usimpleiconseight.fd b/fonts/simpleicons/tex/usimpleiconseight.fd
index 0764655817..1769ab4a24 100644
--- a/fonts/simpleicons/tex/usimpleiconseight.fd
+++ b/fonts/simpleicons/tex/usimpleiconseight.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconseight.fd}[2023/09/08 Font definitions for U/simpleiconseight.]
+ \ProvidesFile{usimpleiconseight.fd}[2023/09/15 Font definitions for U/simpleiconseight.]
\DeclareFontFamily{U}{simpleiconseight}{}
\DeclareFontShape{U}{simpleiconseight}{m}{n}{<-> SimpleIcons--simpleiconseight}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsfive.fd b/fonts/simpleicons/tex/usimpleiconsfive.fd
index e9d397e3df..bfba335887 100644
--- a/fonts/simpleicons/tex/usimpleiconsfive.fd
+++ b/fonts/simpleicons/tex/usimpleiconsfive.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsfive.fd}[2023/09/08 Font definitions for U/simpleiconsfive.]
+ \ProvidesFile{usimpleiconsfive.fd}[2023/09/15 Font definitions for U/simpleiconsfive.]
\DeclareFontFamily{U}{simpleiconsfive}{}
\DeclareFontShape{U}{simpleiconsfive}{m}{n}{<-> SimpleIcons--simpleiconsfive}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsfour.fd b/fonts/simpleicons/tex/usimpleiconsfour.fd
index 842bbfb433..cd501acd81 100644
--- a/fonts/simpleicons/tex/usimpleiconsfour.fd
+++ b/fonts/simpleicons/tex/usimpleiconsfour.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsfour.fd}[2023/09/08 Font definitions for U/simpleiconsfour.]
+ \ProvidesFile{usimpleiconsfour.fd}[2023/09/15 Font definitions for U/simpleiconsfour.]
\DeclareFontFamily{U}{simpleiconsfour}{}
\DeclareFontShape{U}{simpleiconsfour}{m}{n}{<-> SimpleIcons--simpleiconsfour}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsnine.fd b/fonts/simpleicons/tex/usimpleiconsnine.fd
index be3f12280a..6a0177ee55 100644
--- a/fonts/simpleicons/tex/usimpleiconsnine.fd
+++ b/fonts/simpleicons/tex/usimpleiconsnine.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsnine.fd}[2023/09/08 Font definitions for U/simpleiconsnine.]
+ \ProvidesFile{usimpleiconsnine.fd}[2023/09/15 Font definitions for U/simpleiconsnine.]
\DeclareFontFamily{U}{simpleiconsnine}{}
\DeclareFontShape{U}{simpleiconsnine}{m}{n}{<-> SimpleIcons--simpleiconsnine}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsone.fd b/fonts/simpleicons/tex/usimpleiconsone.fd
index 98ecc3103a..83455d9b5f 100644
--- a/fonts/simpleicons/tex/usimpleiconsone.fd
+++ b/fonts/simpleicons/tex/usimpleiconsone.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsone.fd}[2023/09/08 Font definitions for U/simpleiconsone.]
+ \ProvidesFile{usimpleiconsone.fd}[2023/09/15 Font definitions for U/simpleiconsone.]
\DeclareFontFamily{U}{simpleiconsone}{}
\DeclareFontShape{U}{simpleiconsone}{m}{n}{<-> SimpleIcons--simpleiconsone}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsoneone.fd b/fonts/simpleicons/tex/usimpleiconsoneone.fd
index e42c1e3939..2a8dafd044 100644
--- a/fonts/simpleicons/tex/usimpleiconsoneone.fd
+++ b/fonts/simpleicons/tex/usimpleiconsoneone.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsoneone.fd}[2023/09/08 Font definitions for U/simpleiconsoneone.]
+ \ProvidesFile{usimpleiconsoneone.fd}[2023/09/15 Font definitions for U/simpleiconsoneone.]
\DeclareFontFamily{U}{simpleiconsoneone}{}
\DeclareFontShape{U}{simpleiconsoneone}{m}{n}{<-> SimpleIcons--simpleiconsoneone}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsonezero.fd b/fonts/simpleicons/tex/usimpleiconsonezero.fd
index 4e7b08ff8d..062a7ba680 100644
--- a/fonts/simpleicons/tex/usimpleiconsonezero.fd
+++ b/fonts/simpleicons/tex/usimpleiconsonezero.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsonezero.fd}[2023/09/08 Font definitions for U/simpleiconsonezero.]
+ \ProvidesFile{usimpleiconsonezero.fd}[2023/09/15 Font definitions for U/simpleiconsonezero.]
\DeclareFontFamily{U}{simpleiconsonezero}{}
\DeclareFontShape{U}{simpleiconsonezero}{m}{n}{<-> SimpleIcons--simpleiconsonezero}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsseven.fd b/fonts/simpleicons/tex/usimpleiconsseven.fd
index b454ada7ab..8ea617be59 100644
--- a/fonts/simpleicons/tex/usimpleiconsseven.fd
+++ b/fonts/simpleicons/tex/usimpleiconsseven.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsseven.fd}[2023/09/08 Font definitions for U/simpleiconsseven.]
+ \ProvidesFile{usimpleiconsseven.fd}[2023/09/15 Font definitions for U/simpleiconsseven.]
\DeclareFontFamily{U}{simpleiconsseven}{}
\DeclareFontShape{U}{simpleiconsseven}{m}{n}{<-> SimpleIcons--simpleiconsseven}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconssix.fd b/fonts/simpleicons/tex/usimpleiconssix.fd
index 2c0a39aa10..2ed9e26fe4 100644
--- a/fonts/simpleicons/tex/usimpleiconssix.fd
+++ b/fonts/simpleicons/tex/usimpleiconssix.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconssix.fd}[2023/09/08 Font definitions for U/simpleiconssix.]
+ \ProvidesFile{usimpleiconssix.fd}[2023/09/15 Font definitions for U/simpleiconssix.]
\DeclareFontFamily{U}{simpleiconssix}{}
\DeclareFontShape{U}{simpleiconssix}{m}{n}{<-> SimpleIcons--simpleiconssix}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconsthree.fd b/fonts/simpleicons/tex/usimpleiconsthree.fd
index f2eff4313d..0b3b5426e6 100644
--- a/fonts/simpleicons/tex/usimpleiconsthree.fd
+++ b/fonts/simpleicons/tex/usimpleiconsthree.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconsthree.fd}[2023/09/08 Font definitions for U/simpleiconsthree.]
+ \ProvidesFile{usimpleiconsthree.fd}[2023/09/15 Font definitions for U/simpleiconsthree.]
\DeclareFontFamily{U}{simpleiconsthree}{}
\DeclareFontShape{U}{simpleiconsthree}{m}{n}{<-> SimpleIcons--simpleiconsthree}{}
\endinput
diff --git a/fonts/simpleicons/tex/usimpleiconstwo.fd b/fonts/simpleicons/tex/usimpleiconstwo.fd
index 1cd48f57e9..c2e454fb1b 100644
--- a/fonts/simpleicons/tex/usimpleiconstwo.fd
+++ b/fonts/simpleicons/tex/usimpleiconstwo.fd
@@ -1,5 +1,5 @@
- \ProvidesFile{usimpleiconstwo.fd}[2023/09/08 Font definitions for U/simpleiconstwo.]
+ \ProvidesFile{usimpleiconstwo.fd}[2023/09/15 Font definitions for U/simpleiconstwo.]
\DeclareFontFamily{U}{simpleiconstwo}{}
\DeclareFontShape{U}{simpleiconstwo}{m}{n}{<-> SimpleIcons--simpleiconstwo}{}
\endinput
diff --git a/fonts/simpleicons/type1/SimpleIcons.pfb b/fonts/simpleicons/type1/SimpleIcons.pfb
index a4015e4990..ade056b0f8 100644
--- a/fonts/simpleicons/type1/SimpleIcons.pfb
+++ b/fonts/simpleicons/type1/SimpleIcons.pfb
Binary files differ
diff --git a/info/biblio/tugboat.bib b/info/biblio/tugboat.bib
index c5a2a735b6..a5ae93898f 100644
--- a/info/biblio/tugboat.bib
+++ b/info/biblio/tugboat.bib
@@ -2,9 +2,9 @@
%%% ====================================================================
%%% BibTeX-file{
%%% author = "Nelson H. F. Beebe",
-%%% version = "4.12",
-%%% date = "19 May 2023",
-%%% time = "09:10:46 MDT",
+%%% version = "4.13",
+%%% date = "14 September 2023",
+%%% time = "10:50:35 MDT",
%%% filename = "tugboat.bib",
%%% address = "University of Utah
%%% Department of Mathematics, 110 LCB
@@ -14,7 +14,7 @@
%%% telephone = "+1 801 581 5254",
%%% FAX = "+1 801 581 4148",
%%% URL = "https://www.math.utah.edu/~beebe",
-%%% checksum = "28369 108638 367663 3923705",
+%%% checksum = "60761 108663 367833 3925319",
%%% email = "beebe at math.utah.edu, beebe at acm.org,
%%% beebe at computer.org (Internet)",
%%% codetable = "ISO/ASCII",
@@ -43,7 +43,7 @@
%%% issue, access to which requires TUG
%%% membership.
%%%
-%%% At version 4.12, the COMPLETE year coverage
+%%% At version 4.13, the COMPLETE year coverage
%%% looked like this:
%%%
%%% 1980 ( 15) 1995 ( 96) 2010 ( 110)
@@ -4379,6 +4379,7 @@
fjournal = "TUGboat",
issue = "7",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Ion:TB4-1-12,
@@ -12719,6 +12720,7 @@
fjournal = "TUGboat",
issue = "17",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Trevorrow:TB8-1-42,
@@ -20211,6 +20213,7 @@
fjournal = "TUGboat",
issue = "25",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Beeton:TB10-3-314,
@@ -21158,11 +21161,9 @@
ISSN = "0896-3207",
ISSN-L = "0896-3207",
bibdate = "Fri Jul 13 10:24:20 MDT 2007",
- bibsource = "https://www.math.utah.edu/pub/tex/bib/tugboat.bib",
bibsource = "https://www.math.utah.edu/pub/tex/bib/index-table-t.html#tugboat;
https://www.math.utah.edu/pub/tex/bib/tugboat.bib",
URL = "https://tug.org/TUGboat/tb10-3/tb25ads.pdf",
- acknowledgement = ack-nhfb,
acknowledgement = ack-bnb # " and " # ack-nhfb,
fjournal = "TUGboat",
issue = "25",
@@ -21182,11 +21183,9 @@
ISSN = "0896-3207",
ISSN-L = "0896-3207",
bibdate = "Fri Jul 13 10:24:20 MDT 2007",
- bibsource = "https://www.math.utah.edu/pub/tex/bib/tugboat.bib",
bibsource = "https://www.math.utah.edu/pub/tex/bib/index-table-t.html#tugboat;
https://www.math.utah.edu/pub/tex/bib/tugboat.bib",
URL = "https://tug.org/TUGboat/tb10-3/tb25ads.pdf",
- acknowledgement = ack-nhfb,
acknowledgement = ack-bnb # " and " # ack-nhfb,
fjournal = "TUGboat",
issue = "25",
@@ -22132,6 +22131,7 @@
fjournal = "TUGboat",
issue = "27",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Childs:TB11-1-6,
@@ -23077,7 +23077,7 @@
}
@Article{Beebe:TB11-2-171,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "Character set encoding",
journal = j-TUGboat,
volume = "11",
@@ -23095,6 +23095,7 @@
fjournal = "TUGboat",
issue = "28",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Bien:TB11-2-175,
@@ -23800,7 +23801,7 @@
}
@Article{Beebe:TB11-3-335,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "{President}'s introduction",
journal = j-TUGboat,
volume = "11",
@@ -23819,6 +23820,7 @@
fjournal = "TUGboat",
issue = "29",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Mittelbach:TB11-3-337,
@@ -24201,7 +24203,7 @@
}
@Article{Beebe:TB11-3-442,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "{{\TeX} 3.0 and {\MF} 2.0}",
journal = j-TUGboat,
volume = "11",
@@ -24220,6 +24222,7 @@
fjournal = "TUGboat",
issue = "29",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Lammarsch:TB11-3-444,
@@ -24727,6 +24730,7 @@
fjournal = "TUGboat",
issue = "30",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Anonymous:TB11-4-488,
@@ -24790,6 +24794,7 @@
fjournal = "TUGboat",
issue = "30",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Beeton:TB11-4-494,
@@ -28215,6 +28220,7 @@
fjournal = "TUGboat",
issue = "32",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Beeton:TB12-2-208,
@@ -29367,6 +29373,7 @@
fjournal = "TUGboat",
issue = "33",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Poppelier:TB12-3-353,
@@ -29465,8 +29472,8 @@
@Article{Horn:TB12-3-377,
author = "Berthold K. P. Horn",
- title = "{\file{dvi} and \file{eps}: The ideal
- author-to-publisher interface?}",
+ title = "{{\file{dvi} and \file{eps}: The ideal
+ author-to-publisher interface?}}",
journal = j-TUGboat,
volume = "12",
number = "3/4",
@@ -30411,6 +30418,7 @@
fjournal = "TUGboat",
issue = "34",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Beeton:TB13-1-10,
@@ -34948,7 +34956,7 @@
}
@Article{Beebe:TB14-3-222,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "Bibliography prettyprinting and syntax checking",
journal = j-TUGboat,
volume = "14",
@@ -34967,6 +34975,7 @@
fjournal = "TUGboat",
issue = "40",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Bryan:TB14-3-223,
@@ -35856,7 +35865,7 @@
}
@Article{Beebe:TB14-4-395,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "Bibliography prettyprinting and syntax checking",
journal = j-TUGboat,
volume = "14",
@@ -35874,6 +35883,7 @@
fjournal = "TUGboat",
issue = "41",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Carmody:TB14-4-420,
@@ -46210,6 +46220,7 @@
fjournal = "TUGboat",
issue = "58",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Rahtz:TB19-1-19,
@@ -50491,6 +50502,7 @@
fjournal = "TUGboat",
issue = "64",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Bazargan, Kaveh/0000-0002-1414-9098",
}
@Article{Bartlett:TB20-3-221,
@@ -51051,6 +51063,7 @@
fjournal = "TUGboat",
issue = "64",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Bazargan, Kaveh/0000-0002-1414-9098",
}
@Article{Ogawa:TB20-3-326,
@@ -54555,7 +54568,7 @@
ISSN = "0896-3207",
ISSN-L = "0896-3207",
bibdate = "Fri Jul 13 10:24:20 MDT 2007",
- bibsource = "http://www.math.utah.edu/pub/tex/bib/font.bib;
+ bibsource = "https://www.math.utah.edu/pub/tex/bib/font.bib;
https://www.math.utah.edu/pub/tex/bib/index-table-t.html#tugboat;
https://www.math.utah.edu/pub/tex/bib/tugboat.bib",
URL = "https://tug.org/TUGboat/tb22-1-2/tb70zapf.pdf",
@@ -55423,7 +55436,7 @@
}
@Article{Beebe:TB22-3-181,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "{pdf{\TeX} Panel}",
journal = j-TUGboat,
volume = "22",
@@ -55443,6 +55456,7 @@
fjournal = "TUGboat",
issue = "71",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Moore:TB22-3-188,
@@ -55586,7 +55600,7 @@
}
@Article{Beebe:TB22-3-220,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "{Fonts Panel}",
journal = j-TUGboat,
volume = "22",
@@ -55606,6 +55620,7 @@
fjournal = "TUGboat",
issue = "71",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Downes:TB22-3-228,
@@ -59863,6 +59878,7 @@
fjournal = "TUGboat",
issue = "77",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Anonymous:TB24-2-293,
@@ -62161,6 +62177,7 @@
fjournal = "TUGboat",
issue = "80",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
}
@Article{Flynn:TB25-1-31,
@@ -62367,6 +62384,7 @@
fjournal = "TUGboat",
issue = "80",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
remark = "Practical \TeX{} 2004 Proceedings (San Francisco,
California).",
}
@@ -63838,7 +63856,7 @@
}
@Article{Beebe:TB26-1-33,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "{The design of {\TeX} and {\slMF}: A retrospective}",
journal = j-TUGboat,
volume = "26",
@@ -63858,6 +63876,7 @@
fjournal = "TUGboat",
issue = "82",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
remark = "Advanced{\Dash}historical review of the \TeX{} system
software design and development.",
}
@@ -64035,6 +64054,7 @@
fjournal = "TUGboat",
issue = "82",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Bazargan, Kaveh/0000-0002-1414-9098",
remark = "Intermediate{\Dash}interactive parameter setting and
instant feedback.",
}
@@ -68906,6 +68926,7 @@
fjournal = "TUGboat",
issue = "88",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Bazargan, Kaveh/0000-0002-1414-9098",
remark = "Intermediate{\Dash}a method for typesetting on a grid,
including double columns and math.",
}
@@ -70163,7 +70184,7 @@
}
@Article{Beebe:TB28-3-319,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "Extending {\TeX} and {{\sl MF}} with floating-point
arithmetic",
journal = j-TUGboat,
@@ -70184,6 +70205,7 @@
fjournal = "TUGboat",
issue = "90",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
remark = "Advanced{\Dash}floating-point history, problems, and
futures.",
}
@@ -75151,7 +75173,7 @@
}
@Article{Beebe:TB30-2-252,
- author = "Nelson Beebe",
+ author = "Nelson H. F. Beebe",
title = "{{\BibTeX}} meets relational databases",
journal = j-TUGboat,
volume = "30",
@@ -75170,6 +75192,7 @@
fjournal = "TUGboat",
issue = "95",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Beebe, Nelson H. F./0000-0001-7281-4263",
remark = "Intermediate Plus{\Dash}searching large bibliographic
collections using SQL databases.",
}
@@ -75194,6 +75217,7 @@
fjournal = "TUGboat",
issue = "95",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Bazargan, Kaveh/0000-0002-1414-9098",
remark = "Introductory{\Dash}report on using \TeX{} for better
line breaking and mathematics support on the iPhone.",
}
@@ -92344,6 +92368,7 @@
fjournal = "TUGboat",
issue = "116",
journal-URL = "https://tug.org/TUGboat/",
+ ORCID-numbers = "Bazargan, Kaveh/0000-0002-1414-9098",
}
@Article{Anonymous:TB37-2-249,
diff --git a/info/biblio/tugboat.ltx b/info/biblio/tugboat.ltx
index 72a04c116f..3df88a5c98 100644
--- a/info/biblio/tugboat.ltx
+++ b/info/biblio/tugboat.ltx
@@ -6,9 +6,9 @@
%%% ====================================================================
%%% @LaTeX-file{
%%% author = "Nelson H. F. Beebe",
-%%% version = "4.12",
-%%% date = "19 May 2023",
-%%% time = "09:10:33 MDT",
+%%% version = "4.13",
+%%% date = "14 September 2023",
+%%% time = "10:50:39 MDT",
%%% filename = "tugboat.ltx",
%%% address = "University of Utah
%%% Department of Mathematics, 110 LCB
@@ -17,8 +17,8 @@
%%% USA",
%%% telephone = "+1 801 581 5254",
%%% FAX = "+1 801 585 1640, +1 801 581 4148",
-%%% URL = "http://www.math.utah.edu/~beebe",
-%%% checksum = "50181 104 363 3574",
+%%% URL = "https://www.math.utah.edu/~beebe",
+%%% checksum = "50826 104 363 3588",
%%% email = "beebe@math.utah.edu, beebe@acm.org,
%%% beebe@computer.org (Internet)",
%%% codetable = "ISO/ASCII",
@@ -70,11 +70,11 @@
\protect\path=beebe@acm.org=,\\
\hphantom{E-mail:\ }
\protect\path=beebe@computer.org= (Internet)\\
- WWW URL: \protect\path=http://www.math.utah.edu/~beebe/=
+ WWW URL: \protect\path=https://www.math.utah.edu/~beebe/=
}
-\date{19 May 2023 \\
-Version 4.12}
+\date{14 September 2023 \\
+Version 4.13}
\begin{document}
\nocite{*}
diff --git a/macros/latex/contrib/robust-externalize/robust-externalize.pdf b/macros/latex/contrib/robust-externalize/robust-externalize.pdf
index a20079e4cd..50b3a2f806 100644
--- a/macros/latex/contrib/robust-externalize/robust-externalize.pdf
+++ b/macros/latex/contrib/robust-externalize/robust-externalize.pdf
Binary files differ
diff --git a/macros/latex/contrib/robust-externalize/robust-externalize.sty b/macros/latex/contrib/robust-externalize/robust-externalize.sty
index 38f8c6ded5..e61ae871b0 100644
--- a/macros/latex/contrib/robust-externalize/robust-externalize.sty
+++ b/macros/latex/contrib/robust-externalize/robust-externalize.sty
@@ -1,11 +1,13 @@
-\ProvidesPackage{robust-externalize}[1.0 Cache anything (tikz, latex, python) in a robust, efficient and pure way.]
+\ProvidesPackage{robust-externalize}[2.0 Cache anything (tikz, latex, python) in a robust, efficient and pure way.]
% todo: understand why python scripts with raise NameError("42") do not make latex crash.
+% change order argument replace from list, it is hard to read this way
\RequirePackage{pgfkeys} % We use the /robExt/... path to store our keys.
\RequirePackage{pgffor} % For the .list keys
\RequirePackage{graphicx} % For the includegraphics command
\RequirePackage{verbatim} % For the \verbatim command, useful for debugging purpose for instance
\RequirePackage{xsimverb} % To easily write verbatim code to files
+\RequirePackage{etoolbox} % To easily write verbatim code to files
%% TODO list:
% - provide an easy way to use cross-ref, bibtex etc (we just need to add them when writing the file) without recompiling the whole document (we don't want to lose the cache everytime a new bib entry is added) but while preserving.
@@ -23,24 +25,94 @@
%%%%%%%%%%% Utils %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% Utils:
+
+% Debug function: by default, do nothing
+\def\robExtDebugMessage#1{}
+\def\robExtDebugWarning#1{\message{^^J[robExt warning] #1}}
+
+\NewDocumentCommand{\robExtConfigure}{m}{%
+ \pgfkeys{%
+ /robExt/.cd,#1%Do not add a space before the #1!
+ }%
+}
+
% https://tex.stackexchange.com/questions/690700/latex3-elegant-way-to-forward-a-variable-outside-of-the-group
% modified to deal with csname instead
\def\robExtKeepaftergroup#1{%
%\global \expandafter \expandafter \let \csname x:#1\endcsname =\csname #1\endcsname
- \global \expanded{\noexpand \let \expandafter\noexpand\csname x:#1\endcsname =\expandafter\noexpand\csname #1\endcsname}
- \aftergroup\let
+ \global \expanded{\noexpand \let \expandafter\noexpand\csname x:#1\endcsname =\expandafter\noexpand\csname #1\endcsname}%
+ \aftergroup\let%
\expandafter\aftergroup\csname #1\endcsname%
- \expandafter\aftergroup \csname x:\string#1\endcsname
+ \expandafter\aftergroup \csname x:\string#1\endcsname%
}
+\ExplSyntaxOn
+
+%%%
+%%% Expl3 variants
+%%%
+
+\cs_generate_variant:Nn \str_replace_all:Nnn { Nnx }
+\cs_generate_variant:Nn \str_replace_all:Nnn { Nnv }
+\cs_generate_variant:Nn \str_replace_all:Nnn { cnx }
+\cs_generate_variant:Nn \str_replace_all:Nnn { cxx }
+\cs_generate_variant:Nn \str_replace_all:Nnn { NnV }
+\cs_generate_variant:Nn \str_replace_all:Nnn { Nnx }
+\cs_generate_variant:Nn \str_replace_all:Nnn { Nnv }
+
+\cs_generate_variant:Nn \str_set:Nn { NV }
+
+\cs_generate_variant:Nn \tl_rescan:nn { nv }
+\cs_generate_variant:Nn \tl_set_rescan:Nnn { Nnv }
+\cs_generate_variant:Nn \tl_gset_rescan:Nnn { cnv }
+
+\cs_generate_variant:Nn\seq_remove_all:Nn { NV }
+
+%\cs_generate_variant:Nn\tl_set_rescan:cnn { cnv }
+\cs_generate_variant:Nn \iow_now:Nn { NV }
+\cs_generate_variant:Nn \iow_now:Nn { Nx }
+\cs_generate_variant:Nn \iow_open:Nn { Nx }
+\cs_generate_variant:Nn \ior_str_get:NN { Nc }
+
+\cs_generate_variant:Nn \file_if_exist:nTF { xTF }
+
+%%%
+%%% String manipulation
+%%%
+
+\cs_set:Nn \str_set_hash_robust:Nn {
+ \str_set:Nn {#1} {#2}
+ \str_replace_all:Nnx {#1} { ## } { \c_hash_str }
+}
+\cs_generate_variant:Nn \str_set_hash_robust:Nn { cn }
+\cs_generate_variant:Nn \str_set_hash_robust:Nn { cx }
+
+% Double the number of hashes... quite dirty but cannot find any solution or the user need to double it itself
+%% See also https://tex.stackexchange.com/questions/695432/latex3-latex-doubles-the-number-of-hashes-when-storing-them-in-string/695460#695460
+\NewDocumentCommand{\robExtStrSetDoubleHash}{mm}{
+ \str_set:Nn {#1} {#2}
+ \str_replace_all:Nnx {#1} { ## } { \c_hash_str \c_hash_str }
+}
+
+\NewDocumentCommand{\robExtStrSetHashRobust}{mm}{
+ \str_set_hash_robust:Nn {#1} {#2}
+}
+
+\NewDocumentCommand{\robExtRescanHashRobust}{m}{
+ \str_set_hash_robust:Nn \l_robExt_tmp_str {#1}
+ \tl_rescan:nv {}{ l_robExt_tmp_str }
+}
+
+\ExplSyntaxOff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%% SCRIPTS %%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Important: this script is NOT execute by this file, it is only created so that users can remove unused previously cached files by running this script
+%%% outside of LaTeX.
%%% Create scripts to remove useless files:
-%%% Note that we don't override the script if it exists on purpose (the user might have changed it to fits his needs)
+%%% Note that we don't override the script if it exists on purpose (the user might have changed it to fits their needs)
\begin{filecontents}[noheader]{robExt-remove-old-figures.py}
#!/usr/bin/env python3
import os
@@ -93,6 +165,31 @@ if __name__ == '__main__':
\ExplSyntaxOn
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%% Compatibility %%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% These commands exist on really recent kernels (~june 2023), so we provide them in case they do not already exist
+
+\ProvideDocumentCommand \NewEnvironmentCopy {mm} {
+ \expandafter \NewCommandCopy \csname#1\expandafter\endcsname \csname#2\endcsname
+ \expandafter \NewCommandCopy \csname end#1\expandafter\endcsname \csname end#2\endcsname
+}
+
+\ProvideDocumentCommand \RenewEnvironmentCopy {mm} {
+ \expandafter \RenewCommandCopy \csname#1\expandafter\endcsname \csname#2\endcsname
+ \expandafter \RenewCommandCopy \csname end#1\expandafter\endcsname \csname end#2\endcsname
+}
+
+\ProvideDocumentCommand \DeclareEnvironmentCopy {mm} {
+ \expandafter \DeclareCommandCopy \csname#1\expandafter\endcsname \csname#2\endcsname
+ \expandafter \DeclareCommandCopy \csname end#1\expandafter\endcsname \csname end#2\endcsname
+}
+
+\ProvideDocumentCommand \RenewEnvironmentCopy {mm} {
+ \expandafter \RenewCommandCopy \csname#1\expandafter\endcsname \csname#2\endcsname
+ \expandafter \RenewCommandCopy \csname end#1\expandafter\endcsname \csname end#2\endcsname
+}
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%% Paths %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -115,16 +212,19 @@ if __name__ == '__main__':
\NewDocumentCommand{\robExtCheckIfPrefixFolderExists}{}{
% Check if the output directory exists
\ifdefined\robExtCacheFolder
- \sys_if_shell_unrestricted:TF{
+ %% Not sure how to do an "OR" otherwise
+
+ \bool_if:nTF { \sys_if_shell_unrestricted_p: || \cs_if_exist_p:N {\robExtForceCompilation}}
+ {
\ifdefined\robExtDoNotMkdirFolder\else
\ifdefined\robExtManualMode
- \message{If ~ you ~ get~ an~ error,~ make ~ sure ~ to ~ create ~ the ~ folder ~ \robExtCacheFolder.}
+ \message{If ~ you ~ get~ an~ error,~ make ~ sure ~ to ~ enable ~ pdflatex ~ -shell-escape ~ or ~ to ~ manually ~ create ~ the ~ folder ~ \robExtCacheFolder.}
\else
\sys_shell_now:x {mkdir ~ -p ~ \robExtCacheFolder}
\fi
\fi
}{
- \message{If ~ you ~ get~ an~ error,~ make ~ sure ~ to ~ enable ~ pdflatex ~ -shell-escape ~ or ~ to ~ manually ~ create ~ the ~ folder ~ \robExtCacheFolder.}
+ \message{If ~ you ~ get~ an~ error,~ make ~ sure ~ to ~ enable ~ pdflatex ~ -shell-escape ~ or ~ to ~ manually ~ CREATE ~ THE ~ FOLDER ~ \robExtCacheFolder.}
}
\fi
}
@@ -148,20 +248,6 @@ if __name__ == '__main__':
%%%%%%%%%%% Setup new commands and variables %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\cs_generate_variant:Nn\seq_remove_all:Nn { NV }
-\cs_generate_variant:Nn\tl_rescan:nn { nv }
-\cs_generate_variant:Nn\tl_set_rescan:Nnn { Nnv }
-%\cs_generate_variant:Nn\tl_set_rescan:cnn { cnv }
-\cs_generate_variant:Nn \iow_now:Nn { NV }
-\cs_generate_variant:Nn \iow_now:Nn { Nx }
-\cs_generate_variant:Nn \iow_open:Nn { Nx }
-\cs_generate_variant:Nn \ior_str_get:NN { Nc }
-\cs_generate_variant:Nn \str_replace_all:Nnn { NnV }
-\cs_generate_variant:Nn \str_replace_all:Nnn { Nnx }
-\cs_generate_variant:Nn \str_replace_all:Nnn { Nnv }
-\cs_generate_variant:Nn \file_if_exist:nTF { xTF }
-\cs_generate_variant:Nn \str_set:Nn { NV }
-
%% Temporary: used when quickly writing to a file
\iow_new:N \g_robExt_write_iow
\ior_new:N \g_robExt_read_ior
@@ -184,6 +270,7 @@ if __name__ == '__main__':
\str_new:N \l_robExt_currentCompilationCommand
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%% Placeholders %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -192,30 +279,42 @@ if __name__ == '__main__':
%% In practice:
%% - for every placeholder MYPLACEHOLDER, a macro \l_robExt_placeholder_MYPLACEHOLDER_str is created, containing
%% the string to use to replace it
-%% - a sequence \l_robExt_placeholders_seq that is a list of string, contains the list of all placeholders,
+%% - a sequence \l_robExt_placeholder_group_main_seq that is a list of string, contains the list of all placeholders,
%% in a string, like [MYLIBRARY, MAINCONTENT] etc...
%% One issue is that LaTeX does not keep some symbols (e.g. % etc...) when used inside a macro, so we define
%% different commands depending on whether they can be used in a macro or not, whether they should be taken
%% from an external file etc...
-\seq_clear_new:N \l_robExt_placeholders_seq
+\seq_clear_new:N \l_robExt_placeholder_group_main_seq
+
+%%%
+%%% Debug in terminal
+%%%
\NewDocumentCommand{\robExtShowPlaceholder}{sm}{
- \message{Placeholder ~ #2 ~ contains:^^J~ \use:c{l_robExt_placeholder_#2_str}}
- \IfBooleanTF{#1}{\cs_show:c { l_robExt_placeholder_#2_str }}{}
+ \cs_if_exist:cTF {l_robExt_placeholder_#2_str} {
+ \message{Placeholder ~ #2 ~ contains:^^J~ \use:c{l_robExt_placeholder_#2_str}}
+ }{
+ \message{Placeholder ~ #2 ~ does ~ not ~ exist.}
+ }
+ \IfBooleanTF{#1}{}{\show\def}
}
\NewDocumentCommand{\robExtShowPlaceholders}{s}{
\message{List ~ of ~ placeholders:}
- \seq_map_inline:Nn \l_robExt_placeholders_seq {\message{##1,}}
- \IfBooleanTF{#1}{\cs_show:N \l_robExt_placeholders_seq}{}
+ \seq_map_inline:Nn \l_robExt_placeholder_group_main_seq {\message{##1,}}
+ \IfBooleanTF{#1}{}{\show\def}
}
\NewDocumentCommand{\robExtShowPlaceholdersContents}{s}{
\message{List ~ of ~ placeholders:}
- \seq_map_inline:Nn \l_robExt_placeholders_seq {\robExtDebugPlaceholder{##1}}
- \IfBooleanTF{#1}{\cs_show:N \l_robExt_placeholders_seq}{}
+ \seq_map_inline:Nn \l_robExt_placeholder_group_main_seq {\robExtShowPlaceholder*{##1}}
+ \IfBooleanTF{#1}{}{\show\def}
}
+%%%
+%%% Debug in document
+%%%
+
\NewDocumentCommand{\robExtPrintPlaceholderNoReplacement}{sm}{%
% For some reasons, newlines are displayed as \Omega. We need to replace them with \\
% https://tex.stackexchange.com/questions/694716/print-latex3-string-verbatim/694717
@@ -246,7 +345,7 @@ if __name__ == '__main__':
\NewDocumentCommand{\robExtPrintAllPlaceholdersExceptDefaults}{s}{
List ~ of ~ placeholders:\\
- \seq_map_inline:Nn \l_robExt_placeholders_seq {
+ \seq_map_inline:Nn \l_robExt_placeholder_group_main_seq {
% We hide the elements starting with __ROBEXT_
\str_if_in:nnTF { ##1 } { __ROBEXT_ } {
\IfBooleanTF {#1} {
@@ -258,21 +357,24 @@ if __name__ == '__main__':
}
}
\let\printAllPlaceholdersExceptDefaults\robExtPrintAllPlaceholdersExceptDefaults
+\let\printImportedPlaceholdersExceptDefaults\robExtPrintAllPlaceholdersExceptDefaults
\NewDocumentCommand{\robExtPrintAllPlaceholders}{}{
List ~ of ~ placeholders:\\
- \seq_map_inline:Nn \l_robExt_placeholders_seq {- ~ Placeholder ~ called ~ \texttt{\tl_to_str:n {##1}} ~ contains: \robExtPrintPlaceholderNoReplacement{##1}}
+ \seq_map_inline:Nn \l_robExt_placeholder_group_main_seq {- ~ Placeholder ~ called ~ \texttt{\tl_to_str:n {##1}} ~ contains: \robExtPrintPlaceholderNoReplacement{##1}}
}
\let\printAllPlaceholders\robExtPrintAllPlaceholders
+\let\printImportedPlaceholders\robExtPrintAllPlaceholders
+
+%%%
+%%% Evaluation of placeholders
+%%%
\NewDocumentCommand{\robExtEvalPlaceholderNoReplacement}{m}{
- % \scantokens{\use:c{l_robExt_placeholder_#1_str}}
% scantokens add an empty space at the end, so we need to add \empty to avoid it having effects
% https://tex.stackexchange.com/questions/213659/could-someone-further-elucidate-expansion-catcodes-and-scantokens
- %\exp_args:Nx \scantokens {\use:c{l_robExt_placeholder_#1_str}}
\tl_rescan:nv {}{ l_robExt_placeholder_#1_str }
- % \tl_rescan:nc { } { l_robExt_placeholder_#1_str }
}
\let\evalPlaceholderNoReplacement\robExtEvalPlaceholderNoReplacement
@@ -281,41 +383,138 @@ if __name__ == '__main__':
}
\let\getPlaceholderNoReplacement\robExtGetPlaceholderNoReplacement
+\NewDocumentCommand{\robExtRescanPlaceholderInVariableNoReplacement}{mm}{
+ \tl_gset_rescan:cnv {#1} {} { l_robExt_placeholder_#2_str }
+}
+\let\rescanPlaceholderInVariableNoReplacement\robExtRescanPlaceholderInVariableNoReplacement
-% Make sure that the placeholder is in the list \l_robExt_placeholders_seq.
+% Make sure that the placeholder is in the list \l_robExt_placeholder_group_main_seq.
% This should automatically be called by other tools
\NewDocumentCommand{\robExtAddPlaceholderToList}{m}{
+ \cs_if_exist:NTF {\robExtCompletelyDisableWholeImportSystem}{}{
+ % Make sure we have a string here:
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #1 }
+ % First we remove existing occurrences (useful to avoid listing the same macro more than once
+ % if we redefine a macro):
+ \seq_remove_all:NV \l_robExt_placeholder_group_main_seq \l_robExt_tmp_str
+ \seq_put_right:NV \l_robExt_placeholder_group_main_seq \l_robExt_tmp_str
+ }
+}
+\let\robExtImportPlaceholder\robExtAddPlaceholderToList
+\let\importPlaceholder\robExtAddPlaceholderToList
+
+\NewDocumentCommand{\robExtClearImportedPlaceholders}{}{
+ \seq_clear:N \l_robExt_placeholder_group_main_seq
+}
+\let\clearImportedPlaceholders\robExtClearImportedPlaceholders
+
+\NewDocumentCommand{\robExtRemoveImportedPlaceholder}{m}{
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #1 }
+ \seq_remove_all:NV \l_robExt_placeholder_group_main_seq \l_robExt_tmp_str
+}
+\let\removeImportedPlaceholder\robExtRemoveImportedPlaceholder
+
+
+% add it first in the list
+\NewDocumentCommand{\robExtAddPlaceholderToListFirst}{m}{
% Make sure we have a string here:
- \str_set:Nn \l_robExt_tmp_str { #1 }
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #1 }
+ % First we remove existing occurrences (useful to avoid listing the same macro more than once
+ % if we redefine a macro):
+ \seq_remove_all:NV \l_robExt_placeholder_group_main_seq \l_robExt_tmp_str
+ \seq_put_left:NV \l_robExt_placeholder_group_main_seq \l_robExt_tmp_str
+}
+\let\robExtImportPlaceholderFirst\robExtAddPlaceholderToListFirst
+\let\importPlaceholderFirst\robExtAddPlaceholderToListFirst
+
+
+% add it first in the list
+\NewDocumentCommand{\robExtAddPlaceholdersToListFirst}{m}{
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #1 }
+ \seq_set_from_clist:NN \l_tmp_seq \l_robExt_tmp_str
% First we remove existing occurrences (useful to avoid listing the same macro more than once
% if we redefine a macro):
- \seq_remove_all:NV \l_robExt_placeholders_seq \l_robExt_tmp_str
- \seq_put_left:NV \l_robExt_placeholders_seq \l_robExt_tmp_str
+ \seq_map_inline:Nn \l_tmp_seq {
+ % This seems to be required to ensure catcodes are correct before removing the elements:
+ \seq_remove_all:Nn \l_robExt_placeholder_group_main_seq {##1}
+ }
+ \seq_put_left:NV \l_robExt_placeholder_group_main_seq \l_robExt_tmp_str
}
+\let\robExtImportPlaceholdersFirst\robExtAddPlaceholdersToListFirst
+\let\importPlaceholdersFirst\robExtAddPlaceholdersToListFirst
+
+
\NewDocumentCommand{\robExtRemovePlaceholder}{m}{
% This seems to be required to ensure catcodes are correct before removing the elements:
- \str_set:Nn \l_robExt_tmp_str { #1 }
- \seq_remove_all:NV \l_robExt_placeholders_seq \l_robExt_tmp_str
- \expandafter \let \csname l_robExt_placeholder_#1_str \endcsname \undefined
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #1 }
+ % First we check if it exists, no need to loop over everything otherwise
+ \str_if_exist:cTF { l_robExt_placeholder_#1_str } {
+ \seq_remove_all:NV \l_robExt_placeholder_group_main_seq \l_robExt_tmp_str
+ \expandafter \let \csname l_robExt_placeholder_#1_str \endcsname \undefined
+ } { }
}
+\let\removePlaceholder\robExtRemovePlaceholder
+\NewDocumentCommand{\checkIfPlaceholderNameIsLegal}{m}{
+ \cs_if_exist:NTF {\robExtPlaceholderOnlyWithUnderscores} {
+ \str_if_in:nnTF {#1}{__}{}{
+ \PackageError{robExt}{Error:~all~the~placeholders~should~contain~two~consecutive~underscores~in~their~name.}{}
+ }
+ } {
+ \str_if_in:nnTF {#1}{__}{}{
+ \message{WARNING:~we~recommend~to~use~only~placeholders~containing~two~consecutive~underscores~in~their~name.}
+ }
+ }
+}
%% Usage: \placeholderFromContent{MYTITLE}{My slide title}
%% MYTITLE will contain at the end "My slide title"
%% Warning: only LaTeX-friendly code should be placed here, as LaTeX does not preserve some symbols and adds spaces
%% Tested!
-\NewDocumentCommand{\robExtPlaceholderFromContent}{mm}{
- \str_set:cn { l_robExt_placeholder_#1_str } {#2}
- \robExtAddPlaceholderToList{#1}
+%% The star version does NOT import the placeholder (useful for efficiency reasons)
+\NewDocumentCommand{\robExtPlaceholderFromContent}{smm}{
+ \str_set_hash_robust:cn { l_robExt_placeholder_#2_str } {#3}
+ \checkIfPlaceholderNameIsLegal{#2}
+ \ifdefined\robExtCompletelyDisableWholeImportSystem\else% Mostly for time optimizations...
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}%
+ \fi
}
\let\placeholderFromContent\robExtPlaceholderFromContent
\let\robExtSetPlaceholder\robExtPlaceholderFromContent
\let\setPlaceholder\robExtPlaceholderFromContent
-\NewDocumentCommand{\robExtCopyPlaceholder}{mm}{
- \str_set_eq:cc { l_robExt_placeholder_#1_str } { l_robExt_placeholder_#2_str }
- \robExtAddPlaceholderToList{#1}
+
+\NewDocumentCommand{\robExtPlaceholderFromContentFirst}{smm}{
+ \str_set_hash_robust:cn { l_robExt_placeholder_#2_str } {#3}
+ \checkIfPlaceholderNameIsLegal{#2}
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToListFirst{#2}}
+}
+\let\placeholderFromContentFirst\robExtPlaceholderFromContentFirst
+\let\robExtSetPlaceholderFirst\robExtPlaceholderFromContentFirst
+\let\setPlaceholderFirst\robExtPlaceholderFromContentFirst
+
+
+\NewDocumentCommand{\robExtPlaceholderFromString}{smm}{
+ \str_set_eq:cN { l_robExt_placeholder_#2_str } {#3}
+ \checkIfPlaceholderNameIsLegal{#2}
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
+}
+\let\placeholderFromString\robExtPlaceholderFromString
+\let\setPlaceholderFromString\robExtPlaceholderFromString
+
+\NewDocumentCommand{\robExtPlaceholderFromStringExpanded}{smm}{
+ \str_set:cx { l_robExt_placeholder_#2_str } {#3}
+ \checkIfPlaceholderNameIsLegal{#2}
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
+}
+\let\placeholderFromStringExpanded\robExtPlaceholderFromStringExpanded
+\let\setPlaceholderFromStringExpanded\robExtPlaceholderFromStringExpanded
+
+
+\NewDocumentCommand{\robExtCopyPlaceholder}{smm}{
+ \str_set_eq:cc { l_robExt_placeholder_#2_str } { l_robExt_placeholder_#3_str }
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
}
\let\copyPlaceholder\robExtCopyPlaceholder
@@ -324,31 +523,55 @@ if __name__ == '__main__':
%% By default it adds a space in between, unless we use the star version
\NewDocumentCommand{\robExtAddToPlaceholder}{smm}{
\str_if_exist:cTF { l_robExt_placeholder_#2_str } {
- \str_set:Nn \l_tmp_str {#3} %% needed as put_right does not convert to string first
+ \str_set_hash_robust:Nn \l_tmp_str {#3} %% needed as put_right does not convert to string first
\IfBooleanTF{#1}{}{\str_put_right:cn { l_robExt_placeholder_#2_str } { ~ } }
\str_put_right:cV { l_robExt_placeholder_#2_str } \l_tmp_str
}{
- \str_set:cn { l_robExt_placeholder_#2_str } {#3}
+ \str_set_hash_robust:cn { l_robExt_placeholder_#2_str } {#3}
\robExtAddPlaceholderToList{#2}
}
}
\let\addToPlaceholder\robExtAddToPlaceholder
+\NewDocumentCommand{\robExtAddToPlaceholderNoImport}{smm}{
+ \str_if_exist:cTF { l_robExt_placeholder_#2_str } {
+ \str_set_hash_robust:Nn \l_tmp_str {#3} %% needed as put_right does not convert to string first
+ \IfBooleanTF{#1}{}{\str_put_right:cn { l_robExt_placeholder_#2_str } { ~ } }
+ \str_put_right:cV { l_robExt_placeholder_#2_str } \l_tmp_str
+ }{
+ \str_set_hash_robust:cn { l_robExt_placeholder_#2_str } {#3}
+ }
+}
+\let\addToPlaceholderNoImport\robExtAddToPlaceholderNoImport
+
+
%% Add something to the right of the placeholder
%% By default it adds a space in between, unless we use the star version
\NewDocumentCommand{\robExtAddBeforePlaceholder}{smm}{
\str_if_exist:cTF { l_robExt_placeholder_#2_str } {
- \str_set:Nn \l_tmp_str {#3} %% needed as put_right does not convert to string first
+ \str_set_hash_robust:Nn \l_tmp_str {#3} %% needed as put_right does not convert to string first
\IfBooleanTF{#1}{}{\str_put_left:cn { l_robExt_placeholder_#2_str } { ~ } }
\str_put_left:cV { l_robExt_placeholder_#2_str } \l_tmp_str
}{
- \str_set:cn { l_robExt_placeholder_#2_str } {#3}
+ \str_set_hash_robust:cn { l_robExt_placeholder_#2_str } {#3}
\robExtAddPlaceholderToList{#2}
}
}
\let\addBeforePlaceholder\robExtAddBeforePlaceholder
+\NewDocumentCommand{\robExtAddBeforePlaceholderNoImport}{smm}{
+ \str_if_exist:cTF { l_robExt_placeholder_#2_str } {
+ \str_set_hash_robust:Nn \l_tmp_str {#3} %% needed as put_right does not convert to string first
+ \IfBooleanTF{#1}{}{\str_put_left:cn { l_robExt_placeholder_#2_str } { ~ } }
+ \str_put_left:cV { l_robExt_placeholder_#2_str } \l_tmp_str
+ }{
+ \str_set_hash_robust:cn { l_robExt_placeholder_#2_str } {#3}
+ }
+}
+\let\addBeforePlaceholderNoImport\robExtAddBeforePlaceholderNoImport
+
+
% Usage:
% \begin{placeholderFromCode}{HELPERFUNCTION}
% def my_helper_function(bla):
@@ -356,7 +579,8 @@ if __name__ == '__main__':
% \end{placeholderFromCode}
% HELPERFUNCTION will contain at the end "def ..."
% This environment cannot be placed inside any other macro/align/...
-\NewDocumentEnvironment{RobExtPlaceholderFromCode}{m}{%
+\NewDocumentEnvironment{RobExtPlaceholderFromCode}{sm}{%
+ \checkIfPlaceholderNameIsLegal{#2}%
% % debug part
% \str_set:Nn \l_test_str {#1}
% \show\l_test_str
@@ -375,25 +599,32 @@ if __name__ == '__main__':
\ior_str_map_inline:Nn \g_robExt_read_ior {%
\str_gput_right:Nx \l_robExt_tmp {\tl_to_str:N{##1}^^J}%
}%
- \str_set_eq:cN {l_robExt_placeholder_#1_str} \l_robExt_tmp%
- \robExtAddPlaceholderToList{#1}%
- %% Otherwise they will be lost when the environment ends
- \robExtKeepaftergroup{l_robExt_placeholders_seq}%
+ \str_set_eq:cN {l_robExt_placeholder_#2_str} \l_robExt_tmp%
+ \IfBooleanTF {#1} {} {
+ \robExtAddPlaceholderToList{#2}
+ %% Otherwise they will be lost when the environment ends
+ \robExtKeepaftergroup{l_robExt_placeholder_group_main_seq}%
+ }
%% for other variable
- \robExtKeepaftergroup{l_robExt_placeholder_#1_str}%
+ \robExtKeepaftergroup{l_robExt_placeholder_#2_str}%
}%
\let\PlaceholderFromCode\RobExtPlaceholderFromCode
\let\endPlaceholderFromCode\endRobExtPlaceholderFromCode
\let\SetPlaceholderCode\RobExtPlaceholderFromCode
\let\endSetPlaceholderCode\endRobExtPlaceholderFromCode
+\NewDocumentCommand{\robExtKeepPlaceholderAfterGroup}{m}{
+ \robExtKeepaftergroup{l_robExt_placeholder_#1_str}%
+}
+\let\keepPlaceholderAfterGroup\robExtKeepPlaceholderAfterGroup
+
%% Usage:
%% \placeholderPathFromFilename{MYLIBPATH}{mylib.py}
%% This will copy mylib.py in the cache, and set MYLIBPATH to the name of the file in the cache like
%% MYLIBPATH = robExt-abcmylib.py
%% Tested!
-\NewDocumentCommand{\robExtPlaceholderPathFromFilename}{mm}{
- \ior_open:Nn \g_robExt_read_ior {#2}
+\NewDocumentCommand{\robExtPlaceholderPathFromFilename}{smm}{
+ \ior_open:Nn \g_robExt_read_ior {#3}
%% Put the file in l_robExt_tmp_contain_file
\str_clear_new:N \l_robExt_tmp_contain_file
\ior_str_map_inline:Nn \g_robExt_read_ior {
@@ -401,15 +632,15 @@ if __name__ == '__main__':
}
%% computes the new filename based on the md5
\str_clear_new:N \l_robExt_tmp_filename
- \str_set:Nx \l_robExt_tmp_filename_no_prefix {\pdfmdfivesum{\l_robExt_tmp_contain_file}#2}
+ \str_set:Nx \l_robExt_tmp_filename_no_prefix {\pdfmdfivesum{\l_robExt_tmp_contain_file}#3}
%% Writes the content to the file
\robExtCheckIfPrefixFolderExists
\iow_open:Nx \g_robExt_write_iow {\robExtAddCachePathAndName{\l_robExt_tmp_filename_no_prefix}}
\iow_now:NV \g_robExt_write_iow \l_robExt_tmp_contain_file
\iow_close:N \g_robExt_write_iow
%% sets the template name to the relative path to the file
- \str_set:cx { l_robExt_placeholder_#1_str } {\robExtPrefixFilename\l_robExt_tmp_filename_no_prefix}
- \robExtAddPlaceholderToList{#1}
+ \str_set:cx { l_robExt_placeholder_#2_str } {\robExtPrefixFilename\l_robExt_tmp_filename_no_prefix}
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
}
\let\placeholderPathFromFilename\robExtPlaceholderPathFromFilename
@@ -417,16 +648,17 @@ if __name__ == '__main__':
%% \placeholderFromFileContent{MYLIB}{mylib.py}
%% This will set MYLIB to the content of the file mylib.py
%% Tested!
-\NewDocumentCommand{\robExtPlaceholderFromFileContent}{mm}{
- \ior_open:Nn \g_robExt_read_ior {#2}
+\NewDocumentCommand{\robExtPlaceholderFromFileContent}{smm}{
+ \checkIfPlaceholderNameIsLegal{#2}
+ \ior_open:Nn \g_robExt_read_ior {#3}
%% Put the file in l_robExt_tmp_contain_file
\str_clear_new:N \l_robExt_tmp_contain_file
\ior_str_map_inline:Nn \g_robExt_read_ior {
\str_put_right:Nx \l_robExt_tmp_contain_file {\tl_to_str:N{##1}^^J}
}
%% sets the template name to the relative path to the file
- \str_set_eq:cN { l_robExt_placeholder_#1_str } \l_robExt_tmp_contain_file
- \robExtAddPlaceholderToList{#1}
+ \str_set_eq:cN { l_robExt_placeholder_#2_str } \l_robExt_tmp_contain_file
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
}
\let\placeholderFromFileContent\robExtPlaceholderFromFileContent
@@ -436,19 +668,19 @@ if __name__ == '__main__':
%% This will copy "some code" in the cache, and set MYLIBPATH to the name of the file in the cache like
%% MYLIBPATH = robExt-abc.py
%% Tested!
-\NewDocumentCommand{\robExtPlaceholderPathFromContent}{mO{.tex}m}{
- \str_set:Nn \l_robExt_tmp_contain_file {#3}
+\NewDocumentCommand{\robExtPlaceholderPathFromContent}{smO{.tex}m}{
+ \str_set_hash_robust:Nn \l_robExt_tmp_contain_file {#4}
%% computes the new filename based on the md5
\str_clear_new:N \l_robExt_tmp_filename
- \str_set:Nx \l_robExt_tmp_filename_no_prefix {\pdfmdfivesum{\l_robExt_tmp_contain_file}#2}
+ \str_set:Nx \l_robExt_tmp_filename_no_prefix {\pdfmdfivesum{\l_robExt_tmp_contain_file}#3}
%% Writes the content to the file
\robExtCheckIfPrefixFolderExists
\iow_open:Nx \g_robExt_write_iow {\robExtAddCachePathAndName{\l_robExt_tmp_filename_no_prefix}}
\iow_now:NV \g_robExt_write_iow \l_robExt_tmp_contain_file
\iow_close:N \g_robExt_write_iow
%% sets the template name to the relative path to the file
- \str_set:cx { l_robExt_placeholder_#1_str } {\robExtPrefixFilename\l_robExt_tmp_filename_no_prefix}
- \robExtAddPlaceholderToList{#1}
+ \str_set:cx { l_robExt_placeholder_#2_str } {\robExtPrefixFilename\l_robExt_tmp_filename_no_prefix}
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
}
\let\placeholderPathFromContent\robExtPlaceholderPathFromContent
@@ -459,7 +691,7 @@ if __name__ == '__main__':
%% \end{PlaceholderPathFromCode}
%% This will copy "some code" in the cache, and set MYLIBPATH to the name of the file in the cache like
%% MYLIBPATH = robExt-abc.py
-\NewDocumentEnvironment{RobExtPlaceholderPathFromCode}{O{}m}{
+\NewDocumentEnvironment{RobExtPlaceholderPathFromCode}{sO{}m}{
\XSIMfilewritestart*{\jobname-robExt-tmp-file-you-can-remove.tmp}
}{
\XSIMfilewritestop
@@ -471,63 +703,175 @@ if __name__ == '__main__':
}
%% computes the new filename based on the md5
\str_clear_new:N \l_robExt_tmp_filename
- \str_set:Nx \l_robExt_tmp_filename_no_prefix {\pdfmdfivesum{\l_robExt_tmp_contain_file}#1}
+ \str_set:Nx \l_robExt_tmp_filename_no_prefix {\pdfmdfivesum{\l_robExt_tmp_contain_file}#2}
%% Writes the content to the file
\robExtCheckIfPrefixFolderExists
\iow_open:Nx \g_robExt_write_iow {\robExtAddCachePathAndName{\l_robExt_tmp_filename_no_prefix}}
\iow_now:NV \g_robExt_write_iow \l_robExt_tmp_contain_file
\iow_close:N \g_robExt_write_iow
%% sets the template name to the relative path to the file
- \str_set:cx { l_robExt_placeholder_#2_str } {\robExtPrefixFilename\l_robExt_tmp_filename_no_prefix}
- \robExtAddPlaceholderToList{#2}
+ \str_set:cx { l_robExt_placeholder_#3_str } {\robExtPrefixFilename\l_robExt_tmp_filename_no_prefix}
+ \IfBooleanTF {#1} {} {
+ \robExtAddPlaceholderToList{#3}
+ \robExtKeepaftergroup{l_robExt_placeholder_group_main_seq}
+ }
%% Otherwise they will be lost when the environment ends
- \robExtKeepaftergroup{l_robExt_placeholders_seq}
- %% for other variable
- \robExtKeepaftergroup{l_robExt_placeholder_#2_str}
+ \robExtKeepaftergroup{l_robExt_placeholder_#3_str}
}
\let\PlaceholderPathFromCode\RobExtPlaceholderPathFromCode
\let\endPlaceholderPathFromCode\endRobExtPlaceholderPathFromCode
-
-
%%% Evaluate a string by replacing the placeholders until there is none left
%%% the result will be in \robExtResult
-\cs_set:Nn \__replace_until_impossible:N {
+% \cs_set:Nn \replace_until_impossible:N {
+% \str_set:Nn \l_robExt_result_str { ls }
+% }
+
+% backup, we are gona test it
+% %%% Evaluate a string by replacing the placeholders until there is none left
+% %%% the result will be in \robExtResult
+\cs_set:Nn \replace_until_impossible:N {
+ \robExtDebugMessage{We needed to run replace_until_impossible}
+ % Try to replace directly if single placeholder
+ \str_if_exist:cTF { l_robExt_placeholder_ \l_robExt_result_str _str }{
+ \str_set_eq:Nc {\l_robExt_result_str}{ l_robExt_placeholder_ \l_robExt_result_str _str }
+ \str_set:Nn \l_robext_tmp_before {}
+ } {
+ \str_set_eq:NN \l_robext_tmp_before \l_robExt_result_str
+ \seq_map_inline:Nn \l_robExt_placeholder_group_main_seq {
+ \robExtDebugMessage{Trying ~ to ~ replace ##1^^J}
+ \str_if_exist:cTF { l_robExt_placeholder_##1_str } {
+ \str_replace_all:Nnv \l_robExt_result_str { ##1 } { l_robExt_placeholder_##1_str }
+ }{
+ \robExtDebugWarning{WARNING: ~ the ~ placeholder ~ ##1 ~ does ~ not ~ exist.}
+ }
+ }
+ }
+ % In quick mode, we first try to check if the string contains __ since by default all placeholders start with __
+ % If not, no need to do one more run
+ \cs_if_exist:NTF {\robExtPlaceholderOnlyWithUnderscores} {
+ \str_if_in:NnTF { \l_robExt_result_str } { __ } {
+ \str_compare:eNeTF \l_robext_tmp_before = \l_robExt_result_str {
+ % We converged
+ }{
+ % The strings are different: we restart
+ %\message{The strings are different, we restart: It ~ used ~ to ~ be ~\l_robext_tmp_before^^J^^J now it is^^J^^J \l_robExt_result_str}
+ \replace_until_impossible:N { }
+ }
+ }{
+ % We found no __ so we stop before even if a change was made
+ }
+ }{
+ % We compare the result
+ \str_compare:eNeTF \l_robext_tmp_before = \l_robExt_result_str {
+ % \str_set_eq:cN { l_robExt_placeholder_#1_str } \l_robExt_result_str
+ % \robExtAddPlaceholderToList{#1}
+ }{
+ % The strings are different: we restart
+ \replace_until_impossible:N { }
+ }
+ }
+}
+
+\NewDocumentCommand{\robExtGetPlaceholderInResult}{sO{}m}{
+ \str_set_hash_robust:Nn \l_robExt_result_str { #3 }
+ \robExtDebugMessage{Begin to evaluate placeholder^^J \l_robExt_result_str}
+ \replace_until_impossible:N { }
+ \robExtDebugMessage{Ended the replacement^^J \l_robExt_result_str}
+ \tl_if_blank:nTF {#2} {} {
+ % To avoid infinite recursion later and allow concatenation to a placeholder that does not exists
+ % we remove the name of the placeholder at the end
+ \str_remove_all:Nn \l_robExt_result_str { #2 }
+ \str_set_eq:cN { l_robExt_placeholder_#2_str } \l_robExt_result_str
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
+ }
+}
+\let\getPlaceholderInResult\robExtGetPlaceholderInResult
+
+%% like robExtGetPlaceholderInResult put assumes that there is a single placeholder name.
+%% It is used mainly for efficiency as it avoids a loop on all placeholder.
+\NewDocumentCommand{\robExtGetPlaceholderInResultFromSinglePlaceholder}{sO{}m}{
+ \cs_if_exist:cTF { l_robExt_placeholder_#3_str }{
+ \str_set_eq:Nc { \l_robExt_result_str }{ l_robExt_placeholder_#3_str }
+ }{
+ \PackageError{robExt}{[robExtGetPlaceholderInResultFromSinglePlaceholder] ~ The ~ placeholder ~ #3 ~ does ~ not ~ exists.}
+ }
+ \robExtDebugMessage{Starting to replace placeholder #3 to get \l_robExt_result_str}
+ \replace_until_impossible:N { }
+ \robExtDebugMessage{Ended up with \l_robExt_result_str}
+ \tl_if_blank:nTF {#2} {} {
+ % To avoid infinite recursion later and allow concatenation to a placeholder that does not exists
+ % we remove the name of the placeholder at the end
+ \str_remove_all:Nn \l_robExt_result_str { #2 }
+ \str_set_eq:cN { l_robExt_placeholder_#2_str } \l_robExt_result_str
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
+ }
+}
+
+\cs_set:Nn \__replace_from_list:N {
\str_set_eq:NN \l_robext_tmp_before \l_robExt_result_str
- \seq_map_inline:Nn \l_robExt_placeholders_seq {
- \str_replace_all:Nnv \l_robExt_result_str { ##1 } { l_robExt_placeholder_##1_str }
+ \clist_map_inline:Nn {#1} {
+ \str_if_exist:cTF { l_robExt_placeholder_##1_str }{
+ \str_replace_all:Nnv \l_robExt_result_str { ##1 } { l_robExt_placeholder_##1_str }
+ } { }
}
% We compare the result
\str_compare:eNeTF \l_robext_tmp_before = \l_robExt_result_str {
- %\str_set_eq:cN { l_robExt_placeholder_#1_str } \l_robExt_result_str
- %\robExtAddPlaceholderToList{#1}
+ % \str_set_eq:cN { l_robExt_placeholder_#1_str } \l_robExt_result_str
+ % \robExtAddPlaceholderToList{#1}
}{
% The strings are different: we restart
- \__replace_until_impossible:N { }
+ \__replace_from_list:N { #1 }
}
}
-\NewDocumentCommand{\robExtGetPlaceholderInResult}{O{}m}{
- \str_set:Nn \l_robExt_result_str { #2 }
- \__replace_until_impossible:N { }
- \tl_if_blank:nTF {#1} {} {
- % To avoid infinite recursion later and allow concatenation to a placeholder that does not exists
- % we remove the name of the placeholder at the end
- \str_remove_all:Nn \l_robExt_result_str { #1 }
- \str_set_eq:cN { l_robExt_placeholder_#1_str } \l_robExt_result_str
- \robExtAddPlaceholderToList{#1}
+\NewDocumentCommand{\robExtGetPlaceholderInResultReplaceFromList}{smO{}m}{
+ \str_set_hash_robust:Nn \l_robExt_result_str { #4 }
+ \clist_set:Nn \l_robExt_list_placeholder_replace_clist {#2}
+ \__replace_from_list:N { \l_robExt_list_placeholder_replace_clist }
+ \tl_if_blank:nTF {#3} {} {
+ \str_remove_all:Nn \l_robExt_result_str { #3 }
+ \str_set_eq:cN { l_robExt_placeholder_#3_str } \l_robExt_result_str
+ \IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#3}}
}
}
-\let\getPlaceholderInResult\robExtGetPlaceholderInResult
+\let\getPlaceholderInResultReplaceFromList\robExtGetPlaceholderInResultReplaceFromList
+
% Otherwise we need latex3
\def\robExtResult{\l_robExt_result_str}
-\NewDocumentCommand{\robExtSetPlaceholderRec}{mm}{
- \robExtGetPlaceholderInResult[#1]{#2}
+%%%% Same version, but replaces only one (useful sometimes)
+\cs_set:Nn \__replace_n_times:n {
+ \str_set_eq:NN \l_robext_tmp_before \l_robExt_result_str
+ \seq_map_inline:Nn \l_robExt_placeholder_group_main_seq {
+ \str_replace_all:Nnv \l_robExt_result_str { ##1 } { l_robExt_placeholder_##1_str }
+ }
+ \int_compare:nTF { #1 > 1}{
+ \__replace_n_times:n {\int_eval:n {#1-1}}
+ }{}
+}
+
+
+\NewDocumentCommand{\robExtSetPlaceholderRec}{smm}{
+ \IfBooleanTF {#1} {
+ \robExtGetPlaceholderInResult*[#2]{#3}
+ } {
+ \robExtGetPlaceholderInResult[#2]{#3}
+ }
}
\let\setPlaceholderRec\robExtSetPlaceholderRec
+\NewDocumentCommand{\robExtSetPlaceholderRecReplaceFromList}{smmm}{
+ \IfBooleanTF {#1} {
+ \robExtGetPlaceholderInResultReplaceFromList*{#2}[#3]{#4}
+ }{
+ \robExtGetPlaceholderInResultReplaceFromList{#2}[#3]{#4}
+ }
+}
+\let\setPlaceholderRecReplaceFromList\robExtSetPlaceholderRecReplaceFromList
+
+
\NewDocumentCommand{\robExtGetPlaceholder}{O{}m}{
\robExtGetPlaceholderInResult[#1]{#2}
\l_robExt_result_str
@@ -537,19 +881,242 @@ if __name__ == '__main__':
%%% Evaluate a string by replacing the placeholders until there is none left
%%% the result will be in \robExtResult
\NewDocumentCommand{\robExtEvalPlaceholder}{m}{
- \str_set:Nn \l_test_str {#1}
+ \str_set_hash_robust:Nn \l_test_str {#1}
\robExtGetPlaceholderInResult{#1}
\tl_rescan:nv {} { l_robExt_result_str }
}
\let\evalPlaceholder\robExtEvalPlaceholder
+%%% Evaluate a string by replacing the placeholders until there is none left
+%%% the result will be in \robExtResult
+\NewDocumentCommand{\robExtEvalPlaceholderReplaceFromList}{mm}{
+ \str_set_hash_robust:Nn \l_test_str {#2}
+ \robExtGetPlaceholderInResultReplaceFromList{#1}{#2}
+ \tl_rescan:nv {} { l_robExt_result_str }
+}
+\let\evalPlaceholderReplaceFromList\robExtEvalPlaceholderReplaceFromList
+
+%%% Evaluate a placeholder by first trying some strings, then checking if a template is still present (if the
+%%% mode is enabled), and then it continues normally. Mostly for performance reasons.
+\NewDocumentCommand{\robExtEvalPlaceholderStartFromList}{mm}{
+ \str_set_hash_robust:Nn \l_test_str {#2}
+ \robExtGetPlaceholderInResultReplaceFromList{#1}{#2}
+ \cs_if_exist:NTF {\robExtPlaceholderOnlyWithUnderscores} {
+ %% there might be non-important placeholders that are replaced later:
+ \str_set_eq:NN \l_robExt_result_minus_str \l_robExt_result_str
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_OUTPUT_PREFIX__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_SOURCE_FILE__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_OUTPUT_PDF__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_WAY_BACK__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_CACHE_FOLDER__}
+ \str_if_in:NnTF { \l_robExt_result_minus_str } { __ } {
+ \replace_until_impossible:N { }
+ }{
+ }
+ }{ \replace_until_impossible:N { } }
+ \tl_rescan:nv {} { l_robExt_result_str }
+}
+\let\evalPlaceholderStartFromList\robExtEvalPlaceholderStartFromList
+
+
\NewDocumentCommand{\robExtEvalPlaceholderInplace}{m}{
\robExtGetPlaceholderInResult{#1}
\tl_set_rescan:Nnx \l_robExt_tmp_tl {} { \l_robExt_result_str }
- \str_set:cx { l_robExt_placeholder_#1_str } { \l_robExt_tmp_tl }
+ \str_set_hash_robust:cx { l_robExt_placeholder_#1_str } { \l_robExt_tmp_tl }
}
\let\evalPlaceholderInplace\robExtEvalPlaceholderInplace
+\NewDocumentCommand{\robExtEvalPlaceholderInplaceFromSinglePlaceholder}{m}{
+ \robExtGetPlaceholderInResultFromSinglePlaceholder{#1}
+ \tl_set_rescan:Nnx \l_robExt_tmp_tl {} { \l_robExt_result_str }
+ \str_set_hash_robust:cx { l_robExt_placeholder_#1_str } { \l_robExt_tmp_tl }
+}
+\let\evalPlaceholderInplaceFromSinglePlaceholder\robExtEvalPlaceholderInplaceFromSinglePlaceholder
+
+
+% Sometimes two symbols ## (with a different catcode than a normal hash) are added instead of a single #
+\NewDocumentCommand{\robExtPlaceholderDoubleNumberHashesInplace}{m}{
+ \str_replace_all:cxx { l_robExt_placeholder_#1_str } { \c_hash_str } { \c_hash_str \c_hash_str }
+}
+\let\placeholderDoubleNumberHashesInplace\robExtPlaceholderDoubleNumberHashesInplace
+
+\NewDocumentCommand{\robExtPlaceholderHalveNumberHashesInplace}{m}{
+ \str_replace_all:cxx { l_robExt_placeholder_#1_str } { \c_hash_str \c_hash_str } { \c_hash_str }
+}
+\let\placeholderHalveNumberHashesInplace\robExtPlaceholderHalveNumberHashesInplace
+
+\NewDocumentCommand{\robExtPlaceholderReplaceInplace}{mmm}{
+ \str_replace_all:cnn { l_robExt_placeholder_#1_str } { #2 } { #3 }
+}
+\let\placeholderReplaceInplace\robExtPlaceholderReplaceInplace
+
+\NewDocumentCommand{\robExtPlaceholderReplaceInplaceEval}{mmm}{
+ \str_replace_all:cxx { l_robExt_placeholder_#1_str } { #2 } { #3 }
+}
+\let\placeholderReplaceInplaceEval\robExtPlaceholderReplaceInplaceEval
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%% Placeholders groups %%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% I used to put all placeholders into the same group, but it was quite inefficient (latex is really slow)
+% Then I tried to hide this group but keep a single list of all items, but still automatically add items to it:
+% also quite slow, and the list was not so useful anyway.
+% In practice, however, we do not need to put the placeholders created by default in a group: we can just store them
+% in a standalone way, and load them when needed. So now I create the concept of group: people can add placeholders
+% to a group of placeholders to load them later if needed (e.g. to list all placeholders created by this library).
+% The group named "main" will be the main one with imported groups, where stuff like "set placeholder rec" will search for the
+% existing placeholders.
+% The group named "preexisting" will contain the placeholders created by this library (useful mostly for
+% debugging purpose).
+
+\NewDocumentCommand{\robExtAddPlaceholdersToGroup}{mm}{
+ % Make sure we have a string here:
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #2 }
+ \seq_set_from_clist:NN \l_robExt_tmp_seq \l_robExt_tmp_str
+ \cs_if_exist:cTF {l_robExt_placeholder_group_#1_seq}{}{ \seq_clear_new:c {l_robExt_placeholder_group_#1_seq}}
+ % First we remove existing occurrences (useful to avoid listing the same macro more than once
+ % if we redefine a macro):
+ \seq_map_inline:Nn \l_robExt_tmp_seq {
+ \message{Adding ##1 to #1}
+ \seq_remove_all:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ \seq_put_right:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ }
+}
+\let\addPlaceholdersToGroup\robExtAddPlaceholdersToGroup
+
+\NewDocumentCommand{\robExtEnsureGroupPlaceholdersExists}{m}{
+ \cs_if_exist:cTF {l_robExt_placeholder_group_#1_seq}{}{ \seq_clear_new:c {l_robExt_placeholder_group_#1_seq}}
+}
+\let\ensureGroupPlaceholdersExists\robExtEnsureGroupPlaceholdersExists
+
+\NewDocumentCommand{\robExtAddPlaceholdersToGroupBefore}{mm}{
+ % Make sure we have a string here:
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #2 }
+ \seq_set_from_clist:NN \l_robExt_tmp_seq \l_robExt_tmp_str
+ \seq_reverse:N \l_robExt_tmp_seq
+ \cs_if_exist:cTF {l_robExt_placeholder_group_#1_seq}{}{ \seq_clear_new:c {l_robExt_placeholder_group_#1_seq}}
+ % First we remove existing occurrences (useful to avoid listing the same macro more than once
+ % if we redefine a macro):
+ \seq_map_inline:Nn \l_robExt_tmp_seq {
+ \seq_remove_all:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ \seq_put_left:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ }
+}
+\let\addPlaceholdersToGroupBefore\robExtAddPlaceholdersToGroupBefore
+
+\NewDocumentCommand{\robExtRemovePlaceholdersFromGroup}{mm}{
+ % Make sure we have a string here:
+ \str_set_hash_robust:Nn \l_robExt_tmp_str { #2 }
+ \seq_set_from_clist:NN \l_robExt_tmp_seq \l_robExt_tmp_str
+ \seq_reverse:N \l_robExt_tmp_seq
+ \cs_if_exist:cTF {l_robExt_placeholder_group_#1_seq}{}{ \seq_clear_new:c {l_robExt_placeholder_group_#1_seq}}
+ % First we remove existing occurrences (useful to avoid listing the same macro more than once
+ % if we redefine a macro):
+ \seq_map_inline:Nn \l_robExt_tmp_seq {
+ \seq_remove_all:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ }
+}
+\let\removePlaceholdersFromGroup\robExtRemovePlaceholdersFromGroup
+\let\removePlaceholderFromGroup\robExtRemovePlaceholdersFromGroup
+
+\NewDocumentCommand{\robExtClearGroupPlaceholders}{m}{
+ \seq_clear_new:c {l_robExt_placeholder_group_#1_seq}
+}
+\let\clearGroupPlaceholders\robExtClearGroupPlaceholders
+
+\NewDocumentCommand{\robExtCopyGroupPlaceholders}{mm}{
+ \seq_set_eq:cc {l_robExt_placeholder_group_#1_seq} {l_robExt_placeholder_group_#2_seq}
+}
+\let\copyGroupPlaceholders\robExtCopyGroupPlaceholders
+
+\NewDocumentCommand{\robExtAppendGroupPlaceholders}{mm}{
+ \seq_map_inline:cn {l_robExt_placeholder_group_#2_seq} {
+ \seq_remove_all:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ \seq_put_right:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ }
+}
+\let\appendGroupPlaceholders\robExtAppendGroupPlaceholders
+
+\NewDocumentCommand{\robExtAppendBeforeGroupPlaceholders}{mm}{
+ \seq_eq:Nc \l_robExt_tmp_seq {l_robExt_placeholder_group_#2_seq}
+ \seq_reverse:N \l_robExt_tmp_seq
+ \seq_map_inline:Nn \l_robExt_tmp_seq {
+ \seq_remove_all:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ \seq_put_left:cn {l_robExt_placeholder_group_#1_seq} {##1}
+ }
+}
+\let\appendBeforeGroupPlaceholders\robExtAppendBeforeGroupPlaceholders
+
+\NewDocumentCommand{\robExtImportPlaceholdersFromGroup}{m}{
+ \robExtAppendGroupPlaceholders{main}{#1}
+}
+\let\importPlaceholdersFromGroup\robExtImportPlaceholdersFromGroup
+
+\NewDocumentCommand{\robExtImportAllPlaceholders}{}{
+ \seq_map_inline:Nn \l_robExt_list_groups_seq {
+ \robExtImportPlaceholdersFromGroup{##1}
+ }
+}
+\let\importAllPlaceholders\robExtImportAllPlaceholders
+%%%%
+%%%% List groups, mostly for debugging purpose
+%%%%
+
+\seq_new:N \l_robExt_list_groups_seq % contains the list of all groups
+
+\NewDocumentCommand{\robExtRegisterGroupPlaceholders}{m}{
+ \seq_if_exist:cTF {l_robExt_placeholder_group_#1_seq}{}{
+ \seq_clear_new:c {l_robExt_placeholder_group_#1_seq}
+ }
+ \seq_put_right:Nn \l_robExt_list_groups_seq {#1}
+}
+\let\registerGroupPlaceholders\robExtRegisterGroupPlaceholders
+\let\newGroupPlaceholders\robExtRegisterGroupPlaceholders
+
+\NewDocumentCommand{\robExtShowAllRegisteredGroupsAndPlaceholders}{s}{%
+ \seq_map_inline:Nn \l_robExt_list_groups_seq {%
+ \message{^^J- Group ##1: ^^J}%
+ \seq_map_inline:cn {l_robExt_placeholder_group_##1_seq} {%
+ \message{, ####1 }%
+ \IfBooleanTF{#1}{
+ \message{Content:\use:c{l_robExt_placeholder_####1_str}}
+ }{}
+ }%
+ \message{^^J}
+ }
+ \show\def
+}
+\let\showAllRegisteredGroupsAndPlaceholders\robExtShowAllRegisteredGroupsAndPlaceholders
+
+\NewDocumentCommand{\robExtPrintAllRegisteredGroups}{s}{%
+ \seq_map_inline:Nn \l_robExt_list_groups_seq {%
+ \texttt{##1}\par
+ }
+}
+\let\printAllRegisteredGroups\robExtPrintAllRegisteredGroups
+
+\NewDocumentCommand{\robExtPrintAllRegisteredGroupsAndPlaceholders}{s}{%
+ \seq_map_inline:Nn \l_robExt_list_groups_seq {%
+ - ~ Group \texttt{##1}:\par
+ \seq_map_inline:cn {l_robExt_placeholder_group_##1_seq} {%
+ Placeholder \texttt{####1}%
+ \IfBooleanTF {#1}{\robExtPrintPlaceholderNoReplacement{####1}}{\par}
+ }%
+ }
+}
+\let\printAllRegisteredGroupsAndPlaceholders\robExtPrintAllRegisteredGroupsAndPlaceholders
+
+
+% The star version displays the content as well
+\NewDocumentCommand{\robExtPrintGroupPlaceholders}{sm}{%
+ Content~ of~ group~ \texttt{#2}:\par%
+ \seq_map_inline:cn {l_robExt_placeholder_group_#2_seq} {%
+ -~Placeholder ~ \texttt{##1}\par \IfBooleanTF {#1}{\robExtPrintPlaceholderNoReplacement{##1}}{}
+ }%
+}
+\let\printGroupPlaceholders\robExtPrintGroupPlaceholders
+
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%% Dependencies %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -565,6 +1132,14 @@ if __name__ == '__main__':
\show\l_robExt_dependencies
}
+% Useful when compiling commands
+\NewDocumentCommand{\robExtSaveDependencies}{m}{
+ \seq_set_eq:cN {#1} \l_robExt_dependencies
+}
+\NewDocumentCommand{\robExtRestoreDependencies}{m}{
+ \seq_set_eq:Nc \l_robExt_dependencies {#1}
+}
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%% Externalization %%%%%%%%%%%%
@@ -573,7 +1148,7 @@ if __name__ == '__main__':
%% together with a placeholder called __ROBEXT_COMPILATION_COMMAND__ that will contain the command to compile the file
\NewDocumentCommand{\robExtSetCompilationCommand}{m}{
- \robExtSetPlaceholder{__ROBEXT_COMPILATION_COMMAND__} {#1}
+ \robExtSetPlaceholderFirst{__ROBEXT_COMPILATION_COMMAND__} {#1}
}
\NewDocumentCommand{\robExtAddArgumentToCompilationCommand}{m}{
@@ -584,6 +1159,124 @@ if __name__ == '__main__':
%% Alias of robExtFinalFile to \robExtSourceFile, as I don't like anymore the name I chose
%\def\robExtSourceFile{\robExtFinalFile}
+% First is name of sequence for only try (we only replace those and stop), second is name of sequence for first try (we first try with the sequence and
+% then do a more normal thing), third is the name of the placeholder
+\cs_set:Nn \try_to_evaluate_single_placeholder_without_going_to_replace_until_impossible:NNn {
+ %%%%% Take care of the compilation command: might seem a bit weird and convoluted, but this is needed to get really good efficiency
+ %%%%% since \replace_until_impossible:N { } is quite costly, we try to avoid it
+ \cs_if_exist:NTF {#1} { % We only replace fixed state of placeholders
+ \str_set_eq:Nc \l_robExt_result_str {l_robExt_placeholder_#3_str}
+ \seq_map_inline:Nn {#1} {
+ \robExtDebugMessage{replacing ##1 in \l_robExt_result_str}
+ \str_replace_all:Nnv \l_robExt_result_str {##1} {l_robExt_placeholder_##1_str}
+ }
+ \robExtDebugMessage{Cool, we avoided the costly replace (only try).}
+ }{
+ \cs_if_exist:NTF {#2} { % We start by replacing a fixed state of placeholders
+ \str_set_eq:Nc \l_robExt_result_str {l_robExt_placeholder_#3_str}
+ \robExtDebugMessage{We start by replacing a fixed state of placeholders}
+ %\show#2
+ \seq_map_inline:Nn {#2} {
+ \str_if_exist:cTF {l_robExt_placeholder_##1_str} {
+ \str_replace_all:Nnv \l_robExt_result_str {##1} {l_robExt_placeholder_##1_str}
+ } {
+ \robExtDebugMessage{Warning: ~ trying~to~replace~##1~that~does~not~exist.}
+ }
+ }
+ %\show\l_robExt_result_str
+ %% Check if there is some more stuff to replace (possible only if we consider only templates with underscores
+ \cs_if_exist:NTF {\robExtPlaceholderOnlyWithUnderscores} {
+ % all templates have underscores
+ % first check if some non-important elements are here: for this we first remove them
+ \str_set_eq:NN \l_robExt_result_minus_str \l_robExt_result_str
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_OUTPUT_PREFIX__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_SOURCE_FILE__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_OUTPUT_PDF__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_WAY_BACK__}
+ \str_remove_all:Nn \l_robExt_result_minus_str {__ROBEXT_CACHE_FOLDER__}
+ % Now, we check if some __ are left:
+ \str_if_in:NnTF { \l_robExt_result_minus_str } { __ } {
+ % Some templates are left
+ \robExtDebugMessage{Still some templates are left.}
+ \replace_until_impossible:N { }
+ } {
+ % No more template: the end
+ \robExtDebugMessage{Cool, we avoided the costly replace.}
+ }
+ }{
+ % no way to know, must do it anyway
+ \robExtDebugMessage{Seems like not all templates contain underscore. Too bad, it will be slower}
+ \replace_until_impossible:N { }
+ }
+ }{
+ \robExtDebugMessage{No advice on how to start: doing it the long way}
+ \robExtGetPlaceholderInResultFromSinglePlaceholder{#3}
+ }
+ }
+}
+
+\NewDocumentCommand{\robExtOnlyPlaceholdersInCompilationCommand}{m}{
+ \seq_set_from_clist:Nn \robExtOnlyTryThisSequenceOnCompilationCommand {#1}
+}
+\let\onlyPlaceholdersInCompilationCommand\robExtOnlyPlaceholdersInCompilationCommand
+
+\NewDocumentCommand{\robExtFirstPlaceholdersInCompilationCommand}{m}{
+ \seq_set_from_clist:Nn \robExtFirstTryThisSequenceOnCompilationCommand {#1}
+}
+\let\firstPlaceholdersInCompilationCommand\robExtFirstPlaceholdersInCompilationCommand
+
+\NewDocumentCommand{\robExtOnlyPlaceholdersInTemplate}{m}{
+ \seq_set_from_clist:Nn \robExtOnlyTryThisSequenceOnTemplate {#1}
+}
+\let\onlyPlaceholdersInTemplate\robExtOnlyPlaceholdersInTemplate
+
+\NewDocumentCommand{\robExtFirstPlaceholdersInTemplate}{m}{
+ \seq_set_from_clist:Nn \robExtFirstTryThisSequenceOnTemplate {#1}
+}
+\let\firstPlaceholdersInTemplate\robExtFirstPlaceholdersInTemplate
+
+% for use outside of expl3 (pgf)
+\def\robExtCurrentCompilationCommand{\l_robExt_currentCompilationCommand}
+\NewDocumentCommand{\robExtGetNearlyFinalValueTemplateAndCompilationCommand}{}{
+ %% oututs the compilation in \l_robExt_currentCompilationCommand and the template in \l_robExt_result_str
+ %% This is for efficiency reasons: we only allow a few placeholders:
+ %% In compilation command:
+ %%
+ %% In template:
+ %% - __ROBEXT_MAIN_CONTENT__
+ %% - __ROBEXT_MAIN_CONTENT_ORIG__
+ %% - __ROBEXT_LATEX_PREAMBLE__
+ %% - __ROBEXT_OUTPUT_PREFIX__
+ %% - __ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__
+ %% - __ROBEXT_LATEX_CREATE_OUT_FILE__
+ %% Others
+ %% - __ROBEXT_SOURCE_FILE__
+ %% - __ROBEXT_OUTPUT_PDF__
+ %% - __ROBEXT_WAY_BACK__
+ %% - __ROBEXT_CACHE_FOLDER__
+ \ifdefined\robExtDisablePlaceholders%
+ \robExtDebugMessage{You have disabled placeholders (this is likely a compiled template)}%
+ \str_set_eq:NN \l_robExt_currentCompilationCommand \l_robExt_placeholder___ROBEXT_COMPILATION_COMMAND___str
+ \str_set_eq:NN \l_robExt_result_str \l_robExt_placeholder___ROBEXT_TEMPLATE___str%
+ \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_MAIN_CONTENT__} {l_robExt_placeholder___ROBEXT_MAIN_CONTENT___str}
+ \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_LATEX_PREAMBLE__} {l_robExt_placeholder___ROBEXT_LATEX_PREAMBLE___str}
+ \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_MAIN_CONTENT_ORIG__} {l_robExt_placeholder___ROBEXT_MAIN_CONTENT_ORIG___str}
+ \else
+ \ifdefined\robExtEnableImportMechanism\else\robExtImportAllPlaceholders\fi%
+ %%%%% Take care of the compilation command: might seem a bit weird and convoluted, but this is needed to get really good efficiency
+ %%%%% since \replace_until_impossible:N { } is quite costly, we try to avoid it
+ \try_to_evaluate_single_placeholder_without_going_to_replace_until_impossible:NNn \robExtOnlyTryThisSequenceOnCompilationCommand \robExtFirstTryThisSequenceOnCompilationCommand {__ROBEXT_COMPILATION_COMMAND__}
+ \str_set_eq:NN \l_robExt_currentCompilationCommand \l_robExt_result_str
+ %%%%% Take care of
+ \try_to_evaluate_single_placeholder_without_going_to_replace_until_impossible:NNn \robExtOnlyTryThisSequenceOnTemplate \robExtFirstTryThisSequenceOnTemplate {__ROBEXT_TEMPLATE__}
+ \fi
+}
+
+\NewDocumentCommand{\robExtSetBackCompilationCommandAndTemplate}{}{
+ \robExtPlaceholderFromString{__ROBEXT_COMPILATION_COMMAND__}{\l_robExt_currentCompilationCommand}%
+ \robExtPlaceholderFromString{__ROBEXT_TEMPLATE__}{\l_robExt_result_str}%
+}
+
%%% \l_robExt_final_file must contain before calling this function the content of the final file.
%%% \l_robExt_dependencies must contain the extensions (list).
%%% \l_robExt_currentCompilationCommand contains the compilation command to use.
@@ -592,28 +1285,49 @@ if __name__ == '__main__':
\NewDocumentCommand{\robExtWriteFile}{m}{
%%% First we get all dependencies stored in \l_robExt_dependencies to create a csv-like file:
\str_clear:N \l_robExt_dependencies_mdfive
- %% Make sure to remove these placeholders as they should not be replaced.
- %% Not that we cannot just give them their final value here, as it cannot yet be determined without
- %% first computing the md5 hash.
- \robExtRemovePlaceholder{__ROBEXT_SOURCE_FILE__}
- \robExtRemovePlaceholder{__ROBEXT_OUTPUT_PDF__}
- \robExtRemovePlaceholder{__ROBEXT_OUTPUT_PREFIX__}
- \setPlaceholder{__ROBEXT_WAY_BACK__}{\robExtCacheFolderWayBack}
- \robExtEvalPlaceholderInplace{__ROBEXT_WAY_BACK__}
- \setPlaceholder{__ROBEXT_CACHE_FOLDER__}{\robExtCacheFolder}
- \robExtEvalPlaceholderInplace{__ROBEXT_CACHE_FOLDER__}
- %%% We rescan the string in order to evaluate stuff like \myframes into "12,45,56".
- \robExtGetPlaceholderInResult{__ROBEXT_COMPILATION_COMMAND__}
- \ifdefined\robExtDoNotRescanFirstTime
- \str_set_eq:NN \l_robExt_currentCompilationCommand \l_robExt_result_str
- \else
- \tl_set_rescan:Nnx \l_robExt_currentCompilationCommand {} { \l_robExt_result_str }
- \fi%
- %% We get the template
- \robExtGetPlaceholderInResult{__ROBEXT_TEMPLATE__}
- \str_set_eq:NN \l_robExt_final_file_minus_hash_str \l_robExt_result_str
+ \robExtGetNearlyFinalValueTemplateAndCompilationCommand
+ % \ifdefined\robExtDisablePlaceholders%
+ % %% Compilation
+
+ % \str_set_eq:NN \l_robExt_currentCompilationCommand \l_robExt_placeholder___ROBEXT_COMPILATION_COMMAND___str
+ % \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_LATEX_CREATE_OUT_FILE__} {l_robExt_placeholder___ROBEXT_LATEX_CREATE_OUT_FILE___str}
+
+ % \str_set_eq:NN \l_robExt_result_str \l_robExt_placeholder___ROBEXT_TEMPLATE___str%
+ % \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_LATEX_CREATE_OUT_FILE__} {l_robExt_placeholder___ROBEXT_LATEX_CREATE_OUT_FILE___str}
+ % \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__} {l_robExt_placeholder___ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE___str}
+ % % \show\l_robExt_placeholder___ROBEXT_MAIN_CONTENT___str
+ % \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_MAIN_CONTENT__} {l_robExt_placeholder___ROBEXT_MAIN_CONTENT___str}
+ % \str_replace_all:Nnv \l_robExt_result_str {__ROBEXT_MAIN_CONTENT_ORIG__} {l_robExt_placeholder___ROBEXT_MAIN_CONTENT_ORIG___str}
+ % \else%
+ % %% Make sure to remove these placeholders as they should not be replaced.
+ % %% Not that we cannot just give them their final value here, as it cannot yet be determined without
+ % %% first computing the md5 hash.
+ % \ifdefined\robExtEnableImportMechanism\else\robExtImportAllPlaceholders\fi%
+ % % \robExtConfigure{run ~ early ~ before ~ compilation}
+ % % \robExtConfigure{show ~imported~ placeholders}% debug
+ % % \robExtRemovePlaceholder{__ROBEXT_SOURCE_FILE__}
+ % % \robExtRemovePlaceholder{__ROBEXT_OUTPUT_PDF__}
+ % % \robExtRemovePlaceholder{__ROBEXT_OUTPUT_PREFIX__}
+ % % it seems to take non negligible time let us replace them manually
+ % % \robExtPlaceholderFromString{__ROBEXT_WAY_BACK__}{\robExtCacheFolderWayBack}
+ % % \robExtPlaceholderFromString{__ROBEXT_CACHE_FOLDER__}{\robExtCacheFolder}
+ % %%% We rescan the string in order to evaluate stuff like \myframes into "12,45,56".
+ % % \robExtConfigure{run ~ before ~ compilation}
+ % \robExtGetPlaceholderInResultFromSinglePlaceholder{__ROBEXT_COMPILATION_COMMAND__}
+ % % \robExtConfigure{run ~ after ~ compilation}
+ % % \ifdefined\robExtDoNotRescanFirstTime
+ % \str_set_eq:NN \l_robExt_currentCompilationCommand \l_robExt_result_str
+ % % \else
+ % % \tl_set_rescan:Nnx \l_robExt_currentCompilationCommand {} { \l_robExt_result_str }
+ % % \fi%
+ % %% We get the template
+ % % \robExtConfigure{run ~ before ~ template}
+ % \robExtGetPlaceholderInResultFromSinglePlaceholder{__ROBEXT_TEMPLATE__}
+ % % \robExtConfigure{run ~ after ~ template}
+ % \fi%
+ %\str_set_eq:NN \l_robExt_final_file_minus_hash_str \l_robExt_result_str
% We first add on the first line the compilation command, and on the second line the template file.
- \str_set:Nx \l_robExt_dependencies_mdfive {command,\l_robExt_currentCompilationCommand^^J\pdfmdfivesum{\l_robExt_final_file_minus_hash_str ^^J},^^J} %% ^^J is a newline: LaTeX will automatically add a new line when writing the file
+ \str_set:Nx \l_robExt_dependencies_mdfive {command,\l_robExt_currentCompilationCommand^^J\pdfmdfivesum{\l_robExt_result_str ^^J},^^J} %% ^^J is a newline: LaTeX will automatically add a new line when writing the file
\seq_map_inline:Nn \l_robExt_dependencies {
\str_put_right:Nx \l_robExt_dependencies_mdfive {\file_mdfive_hash:n{##1},##1^^J} %% ^^J is a newline
}
@@ -622,21 +1336,22 @@ if __name__ == '__main__':
%% The last newline is needed as the write operation automatically adds a newline.
\tl_set:Nx \robExtFinalHash {\pdfmdfivesum{\l_robExt_dependencies_mdfive^^J}}
%% We add the figure in the list of files.
- \iow_now:Nx \g_robExt_write_list_all_figures {\robExtAddPrefixName{\robExtFinalHash.tex}^^J}
+ \iow_now:Nx \g_robExt_write_list_all_figures {\robExtAddPrefixName{\robExtFinalHash.tex}}
%% We can now set the placeholders, and recompute the final value of the file:
- \robExtPlaceholderFromContent{__ROBEXT_SOURCE_FILE__}{\robExtAddPrefixName{\robExtFinalHash.tex}}
- \robExtEvalPlaceholderInplace{__ROBEXT_SOURCE_FILE__}
- \robExtPlaceholderFromContent{__ROBEXT_OUTPUT_PDF__}{\robExtAddPrefixName{\robExtFinalHash.pdf}}
- \robExtEvalPlaceholderInplace{__ROBEXT_OUTPUT_PDF__}
- \robExtPlaceholderFromContent{__ROBEXT_OUTPUT_PREFIX__}{\robExtAddPrefixName{\robExtFinalHash}}
- \robExtEvalPlaceholderInplace{__ROBEXT_OUTPUT_PREFIX__}
- \robExtGetPlaceholderInResult{__ROBEXT_TEMPLATE__}
- \str_set_eq:NN \l_robExt_final_file_str \l_robExt_result_str
+ %% I was doing before \robExtPlaceholderFromContent + \robExtEvalPlaceholderInplace, but it is too slow
+ \str_set:Nx \l_tmp_output_prefix_str {\robExtAddPrefixName{\robExtFinalHash}}
+ %%% No need to re-evaluate from scratch the string,
+ \str_replace_all:Nnx \l_robExt_result_str {__ROBEXT_OUTPUT_PREFIX__}{\l_tmp_output_prefix_str}
+ \str_replace_all:Nnx \l_robExt_result_str {__ROBEXT_SOURCE_FILE__}{\l_tmp_output_prefix_str .tex}
+ \str_replace_all:Nnx \l_robExt_result_str {__ROBEXT_OUTPUT_PDF__}{\l_tmp_output_prefix_str .pdf}
+ \str_replace_all:Nnx \l_robExt_result_str {__ROBEXT_WAY_BACK__}{\robExtCacheFolderWayBack}
+ \str_replace_all:Nnx \l_robExt_result_str {__ROBEXT_CACHE_FOLDER__}{\robExtCacheFolder}
+ %\str_set_eq:NN \l_robExt_final_file_str \l_robExt_result_str
\file_if_exist:xTF{\robExtAddCachePathAndName{\robExtFinalHash.tex}}{
\message{The\space file\space \robExtAddCachePathAndName{\robExtFinalHash.tex} \space already\space exists.^^J}
}{
- \str_if_empty:NTF \l_robExt_final_file_str {
- \PackageError{robExt}{You ~ are ~ writing ~ an ~ empty ~ tex ~ file, ~ that ~ will ~ fail ~ to ~ compile. ~ Make ~ sure ~ you ~ defined ~ a ~ template.}{}
+ \str_if_eq:VnTF { \l_robExt_result_str }{__ROBEXT_TEMPLATE__} {
+ \PackageError{robExt}{You ~ are ~ writing ~ __ROBEXT_TEMPLATE__ ~ to ~ your ~ file: ~ seems ~ like ~ you ~ forgot ~ to ~ define ~ your ~ template ~ or ~ set ~ a ~ preset}{}
}{
% Check if the output directory exists
\robExtCheckIfPrefixFolderExists
@@ -645,7 +1360,7 @@ if __name__ == '__main__':
\iow_close:N \g_robExt_write_iow
%% Save the final file:
\iow_open:Nx \g_robExt_write_iow {\robExtAddCachePathAndName{\robExtFinalHash.tex}}
- \iow_now:NV \g_robExt_write_iow \l_robExt_final_file_str
+ \iow_now:NV \g_robExt_write_iow \l_robExt_result_str
\iow_close:N \g_robExt_write_iow
\message{Source ~ saved ~ in ~ \robExtAddCachePathAndName{\robExtFinalHash.tex}.}
}
@@ -659,34 +1374,71 @@ if __name__ == '__main__':
\file_if_exist:xTF{\robExtAddCachePathAndName{\robExtFinalHash.pdf}}{
\message{No ~ need ~ to ~ recompile ~ \robExtAddCachePathAndName{\robExtFinalHash.pdf}^^J}
}{
- \robExtGetPlaceholderInResult{__ROBEXT_COMPILATION_COMMAND__}
- \ifdefined\robExtDoNotRescanSecondTime
- \str_set_eq:NN \l_robExt_finalCompilationCommand \l_robExt_result_str
- \else
- \tl_set_rescan:Nnx \l_robExt_finalCompilationCommand {} { \l_robExt_result_str }
- \fi%
+ % No need to re-evaluate it
+ % \robExtGetPlaceholderInResultFromSinglePlaceholder{__ROBEXT_COMPILATION_COMMAND__}
+ \str_replace_all:Nnx \l_robExt_currentCompilationCommand {__ROBEXT_OUTPUT_PREFIX__}{\l_tmp_output_prefix_str}
+ \str_replace_all:Nnx \l_robExt_currentCompilationCommand {__ROBEXT_SOURCE_FILE__}{\l_tmp_output_prefix_str .tex}
+ \str_replace_all:Nnx \l_robExt_currentCompilationCommand {__ROBEXT_OUTPUT_PDF__}{\l_tmp_output_prefix_str .pdf}
+ \str_replace_all:Nnx \l_robExt_currentCompilationCommand {__ROBEXT_WAY_BACK__}{\robExtCacheFolderWayBack}
+ \str_replace_all:Nnx \l_robExt_currentCompilationCommand {__ROBEXT_CACHE_FOLDER__}{\robExtCacheFolder}
+ % \ifdefined\robExtDoNotRescanSecondTime
+ % \str_set_eq:NN \l_robExt_finalCompilationCommand \l_robExt_currentCompilationCommand
+ % \else
+ % \tl_set_rescan:Nnx \l_robExt_finalCompilationCommand {} { \l_robExt_currentCompilationCommand }
+ % \fi%
% Make sure this command is run from the cache folder
\ifdefined\robExtCacheFolder
- \str_put_left:Nx \l_robExt_finalCompilationCommand {cd ~ \robExtCacheFolder \space && ~ }
+ \str_put_left:Nx \l_robExt_currentCompilationCommand {cd ~ \robExtCacheFolder \space && ~ }
\fi
\ifdefined\robExtManualMode
- \message{[robExt] Manual mode enabled: please, manually compile the images using \l_robExt_finalCompilationCommand or run 'bash \jobname-\robExtAddPrefixName{compile-missing-figures.sh}'.}
- \iow_now:Nx \g_robExt_write_manually_compile_all_missing_figures {\l_robExt_finalCompilationCommand^^J}
+ \message{[robExt] Manual mode enabled: please, manually compile the images using \l_robExt_currentCompilationCommand or run 'bash \jobname-\robExtAddPrefixName{compile-missing-figures.sh}'.}
+ \iow_now:Nx \g_robExt_write_manually_compile_all_missing_figures {\l_robExt_currentCompilationCommand}% a new line is automatically added
\else
- \sys_if_shell_unrestricted:TF{
- \message{[robExt] We ~ will ~ start ~ the ~ compilation using: ~ \l_robExt_finalCompilationCommand.}
- \sys_shell_now:x {\l_robExt_finalCompilationCommand} % The ~ are used in ExplSyntaxOn to add space
+ \bool_if:nTF { \sys_if_shell_unrestricted_p: || \cs_if_exist_p:N {\robExtForceCompilation} }
+ {
+ \message{[robExt] We ~ will ~ start ~ the ~ compilation using: ~ \l_robExt_currentCompilationCommand.}
+ \sys_shell_now:x {\l_robExt_currentCompilationCommand} % The ~ are used in ExplSyntaxOn to add space
}{
- \PackageError{robExt}{You ~ need ~ to ~ compile ~ with ~ shell-escape ~ as ~ in: ~ "pdflatex ~ -shell-escape ~ yourfile.tex" ~ to ~ be ~ able ~ to ~ compile ~ automatically ~ the ~ figures}{}
+ \ifdefined\robExtFallbackManualMode
+ \message{[robExt] Fallback to manual mode: please, manually compile the images using \l_robExt_currentCompilationCommand or run 'bash \jobname-\robExtAddPrefixName{compile-missing-figures.sh}'.}
+ \iow_now:Nx \g_robExt_write_manually_compile_all_missing_figures {\l_robExt_currentCompilationCommand}% a new line is automatically added
+ \else
+ \PackageError{robExt}{You ~ need ~ to ~ compile ~ with ~ shell-escape ~ as ~ in: ~ "pdflatex ~ -shell-escape ~ yourfile.tex" ~ to ~ be ~ able ~ to ~ compile ~ automatically ~ the ~ figures}{}
+ \fi
}
\fi
}
}
+\robExtSetPlaceholder*{__ROBEXT_INCLUDE_COMMAND__}{%
+ \ifdefined\robExtDepth%
+ \raisebox{-\robExtDepth}{%
+ \includegraphics[__ROBEXT_INCLUDEGRAPHICS_OPTIONS__]{%
+ __ROBEXT_INCLUDEGRAPHICS_FILE__%
+ }}%
+ \else%
+ \includegraphics[__ROBEXT_INCLUDEGRAPHICS_OPTIONS__]{%
+ %\robExtAddCachePathAndName{\robExtFinalHash.pdf}%
+ __ROBEXT_INCLUDEGRAPHICS_FILE__%
+ }%
+ \fi
+}
+
+% These special placeholders are not loaded before for efficiency reasons.
+\NewDocumentCommand{\robExtLoadSpecialPlaceholders}{}{
+ \robExtPlaceholderFromString {__ROBEXT_OUTPUT_PREFIX__}{\l_tmp_output_prefix_str}
+ \robExtPlaceholderFromStringExpanded {__ROBEXT_SOURCE_FILE__}{\l_tmp_output_prefix_str .tex}
+ \robExtPlaceholderFromStringExpanded {__ROBEXT_OUTPUT_PDF__}{\l_tmp_output_prefix_str .pdf}
+ \robExtPlaceholderFromStringExpanded {__ROBEXT_WAY_BACK__}{\robExtCacheFolderWayBack}
+ \robExtPlaceholderFromStringExpanded {__ROBEXT_CACHE_FOLDER__}{\robExtCacheFolder}
+}
+
\def\robExtIncludeGraphicsArgs{}
%%% This command is not meant to be called by the end user. It will be called after the compilation to include
%%% the compiled file back into the original file.
\NewDocumentCommand{\robExtIncludeFile}{m}{%
+ % We can disable this loading for efficiency reasons
+ \ifdefined\robExtDoNotLoadSpecialPlaceholders\else\robExtLoadSpecialPlaceholders\fi%
\ifdefined\robExtIncludeCommandAdvanced%
\robExtIncludeCommandAdvanced%
\else%
@@ -697,39 +1449,95 @@ if __name__ == '__main__':
% https://tex.stackexchange.com/questions/104034/when-is-it-good-practice-to-use-unskip
\input{\robExtAddCachePathAndName{\robExtFinalHash-out.tex}}\unskip% Otherwise if the file contains space it will be added here.
}{}%
+ %\robExtConfigure{run ~ before ~ include ~ command}%
\ifdefined\robExtIncludeCommand%
\robExtIncludeCommand%
\else%
- \evalPlaceholder{%
- \ifdefined\robExtDepth%
- \raisebox{-\robExtDepth}{%
- \includegraphics[__ROBEXT_INCLUDEGRAPHICS_OPTIONS__]{%
- __ROBEXT_INCLUDEGRAPHICS_FILE__%
- }}%
- \else%
- \includegraphics[__ROBEXT_INCLUDEGRAPHICS_OPTIONS__]{%
- \robExtAddCachePathAndName{\robExtFinalHash.pdf}}%
- }%
- \fi%
+\robExtEvalPlaceholderStartFromList{__ROBEXT_INCLUDE_COMMAND__,__ROBEXT_INCLUDEGRAPHICS_OPTIONS__,__ROBEXT_INCLUDEGRAPHICS_FILE__,__ROBEXT_LATEX_TRIM_LENGTH__}{__ROBEXT_INCLUDE_COMMAND__}%
\fi%
+ %\robExtConfigure{run ~ after ~ include ~ command}%
}{
\ifdefined\robExtManualMode
\framebox[\linewidth]
{
\begin{minipage}{\linewidth}
- \textbf{Draft ~ Mode: ~ you ~ are ~ in ~ manual ~ mode: ~ please ~ compile ~ \robExtAddCachePathAndName{\robExtFinalHash.tex} ~ via ~ ``\l_robExt_finalCompilationCommand'' ~ or ~ call ~ ``bash ~ \jobname-\robExtAddPrefixName{compile-missing-figures.sh'' ~ to ~ compile ~ all ~ missing ~ figures.}}
+ \textbf{Draft ~ mode: ~ either ~ compile ~ with ~ \texttt{-shell-escape} ~ or ~ compile:\newline \texttt{\robExtAddCachePathAndName{\robExtFinalHash.tex}}\newline via ~ \newline \texttt{\l_robExt_currentCompilationCommand}\newline or ~ call ~ \newline\texttt{bash ~ \jobname-\robExtAddPrefixName{compile-missing-figures.sh}}\newline to ~ compile ~ all ~ missing ~ figures.}
\end{minipage}
}
%\fbox{\textbf{Draft ~ Mode: ~ you ~ are ~ in ~ manual ~ mode:}\par\textbf{ ~ please ~ compile ~ \robExtAddCachePathAndName{\robExtFinalHash.tex} ~ or ~ use ~ \ifdefined\robExtCacheFolder cd \robExtCacheFolder; \fi bash ~ \jobname-\robExtAddPrefixName{compile-missing-figures.sh}}}
\message{[robExt] ~ You ~ are ~ in ~ manual ~ mode: ~ please ~ compile ~ yourself ~ \robExtAddCachePathAndName{\robExtFinalHash.tex} ~ or ~ use ~ the ~ bash ~ \jobname-\robExtAddPrefixName{compile-missing-figures.sh}}
\else
- \PackageError{robExt}{For ~ an ~ unknown ~ reason ~ the ~ pdf ~ file ~ \robExtAddCachePathAndName{\robExtFinalHash.pdf} ~ is ~ not ~ present. ~ The ~ compilation ~ command ~ certainly ~ failed, ~ see ~ logs ~ above.}{}
+ \ifdefined\robExtFallbackManualMode
+ \framebox[\linewidth]
+ {
+ \begin{minipage}{\linewidth}
+ \textbf{Falling ~ back ~ to ~ draft ~ mode: ~ either ~ compile ~ with ~ \texttt{-shell-escape} ~ or ~ compile:\newline \texttt{\robExtAddCachePathAndName{\robExtFinalHash.tex}}\newline via ~ \newline \texttt{\l_robExt_currentCompilationCommand}\newline or ~ call ~ \newline\texttt{bash ~ \jobname-\robExtAddPrefixName{compile-missing-figures.sh}}\newline to ~ compile ~ all ~ missing ~ figures.}
+ \end{minipage}
+ }
+ % \fbox{\textbf{Draft ~ Mode: ~ you ~ are ~ in ~ manual ~ mode:}\par\textbf{ ~ please ~ compile ~ \robExtAddCachePathAndName{\robExtFinalHash.tex} ~ or ~ use ~ \ifdefined\robExtCacheFolder cd \robExtCacheFolder; \fi bash ~ \jobname-\robExtAddPrefixName{compile-missing-figures.sh}}}
+ \message{[robExt] ~ You ~ are ~ falling ~ back ~ to ~ manual ~ mode: ~ please ~ compile ~ yourself ~ \robExtAddCachePathAndName{\robExtFinalHash.tex} ~ or ~ use ~ the ~ bash ~ \jobname-\robExtAddPrefixName{compile-missing-figures.sh}}
+ \else
+ \PackageError{robExt}{For ~ an ~ unknown ~ reason ~ the ~ pdf ~ file ~ \robExtAddCachePathAndName{\robExtFinalHash.pdf} ~ is ~ not ~ present. ~ The ~ compilation ~ command ~ certainly ~ failed, ~ see ~ logs ~ above.}{}
+ \fi
\fi
- }
+ }%
}%
\fi%
}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Disabling externalization
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% It seems that when we disable externalization on \tikz, \tikz internally call \tikzpicture in a
+% weird way (certainly some tikz magic), and as a result it does not manage to grab the end of the CacheMe
+% environment. For this reason, by default, |disable externalization| will disable **all** commands
+
+\seq_clear_new:N \l_commands_to_reset_seq % List of commands to reset by default when disable externalization is set
+
+\NewDocumentCommand{\robExtAddToCommandResetList}{m}{
+ \seq_put_right:Nn \l_commands_to_reset_seq {#1}
+}
+
+\NewDocumentCommand{\robExtSetCommandResetList}{m}{
+ \seq_set_from_clist:Nn \l_commands_to_reset_seq {#1}
+}
+
+\seq_clear_new:N \l_environments_to_reset_seq % List of environments to reset by default when disable externalization is set
+
+\NewDocumentCommand{\robExtAddToEnvironmentResetList}{m}{
+ \seq_put_right:Nn \l_environments_to_reset_seq {#1}
+}
+
+\NewDocumentCommand{\robExtSetEnvironmentResetList}{m}{
+ \seq_set_from_clist:Nn \l_environments_to_reset_seq {#1}
+}
+
+\NewDocumentCommand{\robExtDisableTikzpictureOverwrite}{}{%
+ \ifdefined\robExtTikzPictureOrig%
+ \let\tikzpicture\robExtTikzPictureOrig%
+ \let\endtikzpicture\endrobExtTikzPictureOrig%
+ \fi%
+ \ifdefined\robExtEnvironmentOrigName%
+ \expanded{\noexpand\DeclareEnvironmentCopy{\robExtEnvironmentOrigName}{robExtEnvironmentOrig\robExtEnvironmentOrigName}}%
+ \fi%
+ \ifdefined\robExtCommandOrigName%
+ \expandafter\DeclareCommandCopy\csname \robExtCommandOrigName\expandafter\endcsname\csname robExtCommandOrig\robExtCommandOrigName\endcsname%
+ \fi%
+ \ifdefined\robExtDoNotResetAllCommands\else%
+ \seq_map_inline:Nn \l_commands_to_reset_seq {
+ \cs_if_exist:cTF { robExtCommandOrig##1 } {
+ \expandafter\DeclareCommandCopy\csname ##1\expandafter\endcsname\csname robExtCommandOrig##1\endcsname%
+ } {}
+ }
+ \seq_map_inline:Nn \l_environments_to_reset_seq {
+ \cs_if_exist:cTF { robExtEnvironmentOrig##1 } {
+ \expanded{\noexpand\DeclareEnvironmentCopy{##1}{robExtEnvironmentOrig##1}}
+ } {}
+ }
+ \fi%
+}
+
\ExplSyntaxOff
@@ -741,29 +1549,245 @@ if __name__ == '__main__':
/robExt/.cd,
% We create a default style that will be loaded (mostly for the user)
default style/.style={},
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%% Code to create new styles %%%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % The advantage of this over .append style is that you do not need to double the number of hashes
+ % don't know if there is a better solution.
+ % https://tex.stackexchange.com/questions/695432/latex3-latex-doubles-the-number-of-hashes-when-storing-them-in-string/695461
+ add to preset/.code 2 args={%
+ \robExtStrSetDoubleHash{\robExtTmpStr}{#2}%
+ % Sadly, \expanded{\noexpand } does not work, as I get extra {} around the def, creating a group
+ % so the simpler seems to use this library ^^
+ \robExtPlaceholderFromString{__ROBEXT_TMP__}{\robExtTmpStr}%
+ \robExtEvalPlaceholderReplaceFromList{__ROBEXT_TMP__}{%
+ \pgfkeys{%
+ /robExt/.cd,
+ #1/.append style={__ROBEXT_TMP__},%
+ }%
+ }%
+ \robExtRemovePlaceholder{__ROBEXT_TMP__}% let us clean our variables
+ },
+ new preset/.code 2 args={%
+ \robExtStrSetDoubleHash{\robExtTmpStr}{#2}%
+ % Sadly, \expanded{\noexpand } does not work, as I get extra {} around the def, creating a group
+ % so the simpler seems to use this library ^^
+ \robExtPlaceholderFromString{__ROBEXT_TMP__}{\robExtTmpStr}%
+ % \robExtShowPlaceholder*{__ROBEXT_TMP__}
+ \robExtEvalPlaceholderReplaceFromList{__ROBEXT_TMP__}{%
+ \pgfkeys{%
+ /robExt/.cd,
+ #1/.style={__ROBEXT_TMP__},%
+ }%
+ }%
+ \robExtRemovePlaceholder{__ROBEXT_TMP__}% let us clean our variables
+ },
+ % new compiled preset={latex compiled}{
+ % code to compile in order to produce the expected strings
+ % }{
+ % code to initialize
+ % }
+ compile latex template/.style={
+ % to allow later addition to the preamble, we add a dummy value that we replace in a few lines
+ % same for main content and content orig that we do not want to replace.
+ add to placeholder={__ROBEXT_LATEX_PREAMBLE__}{__ROBEXT_LATEX_PREAMBLE_DUMMY__},
+ set placeholder={__ROBEXT_MAIN_CONTENT__}{__ROBEXT_MAIN_CONTENT_DUMMY__},
+ set placeholder={__ROBEXT_MAIN_CONTENT_ORIG__}{__ROBEXT_MAIN_CONTENT_ORIG_DUMMY__},
+ /utils/exec={%
+ \robExtGetNearlyFinalValueTemplateAndCompilationCommand%
+ \robExtSetBackCompilationCommandAndTemplate%
+ },
+ set placeholder={__ROBEXT_LATEX_PREAMBLE_DUMMY__}{__ROBEXT_LATEX_PREAMBLE__},
+ set placeholder={__ROBEXT_MAIN_CONTENT_DUMMY__}{__ROBEXT_MAIN_CONTENT__},
+ set placeholder={__ROBEXT_MAIN_CONTENT_ORIG_DUMMY__}{__ROBEXT_MAIN_CONTENT_ORIG__},
+ set placeholder rec replace from list={__ROBEXT_TEMPLATE__,__ROBEXT_LATEX_PREAMBLE_DUMMY__,__ROBEXT_MAIN_CONTENT_DUMMY__,__ROBEXT_MAIN_CONTENT_ORIG_DUMMY__}{__ROBEXT_TEMPLATE__}{__ROBEXT_TEMPLATE__},
+ % For the include command
+ set placeholder rec replace from list={__ROBEXT_INCLUDE_COMMAND__,__ROBEXT_INCLUDEGRAPHICS_OPTIONS__,__ROBEXT_INCLUDEGRAPHICS_FILE__,__ROBEXT_LATEX_TRIM_LENGTH__}{__ROBEXT_INCLUDE_COMMAND__}{__ROBEXT_INCLUDE_COMMAND__},
+ },
+ keep placeholder after group/.code={\robExtKeepPlaceholderAfterGroup{#1}},
+ new compiled preset/.code n args={3}{
+ \robExtStrSetDoubleHash{\robExtCodeToCompileStr}{#2}%
+ \robExtStrSetDoubleHash{\robExtCodeToRunStr}{#3}%
+ % Sadly, \expanded{\noexpand } does not work, as I get extra {} around the def, creating a group
+ % so the simpler seems to use this library ^^
+ \robExtPlaceholderFromString{__ROBEXT_TMP_CODE_TO_COMPILE__}{\robExtCodeToCompileStr}%
+ \robExtPlaceholderFromString{__ROBEXT_TMP_CODE_TO_RUN__}{\robExtCodeToRunStr}%
+ \robExtPlaceholderFromString{__ROBEXT_NAME_TEMPLATE_PREFIX__}{\robExtCodeToRunStr}%
+ % \robExtShowPlaceholder*{__ROBEXT_TMP__}
+ \robExtEvalPlaceholderReplaceFromList{__ROBEXT_TMP_CODE_TO_COMPILE__,__ROBEXT_TMP_CODE_TO_RUN__}{%
+ \robExtConfigure{%
+ #1-recompile/.code={%
+ \begingroup%
+ \robExtConfigure{
+ __ROBEXT_TMP_CODE_TO_COMPILE__,
+ }%
+ \robExtCopyPlaceholder*{__ROBEXT_COMPILED_#1_TEMPLATE__}{__ROBEXT_TEMPLATE__}%
+ \robExtKeepPlaceholderAfterGroup{__ROBEXT_COMPILED_#1_TEMPLATE__}%
+ \robExtCopyPlaceholder*{__ROBEXT_COMPILED_#1_COMPILATION_COMMAND__}{__ROBEXT_COMPILATION_COMMAND__}%
+ \robExtKeepPlaceholderAfterGroup{__ROBEXT_COMPILED_#1_COMPILATION_COMMAND__}%
+ \robExtCopyPlaceholder*{__ROBEXT_COMPILED_#1_INCLUDE_COMMAND__}{__ROBEXT_INCLUDE_COMMAND__}%
+ \robExtKeepPlaceholderAfterGroup{__ROBEXT_COMPILED_#1_INCLUDE_COMMAND__}%
+ \robExtRescanPlaceholderInVariableNoReplacement{robExtCompiledIncludeCommand#1}{__ROBEXT_INCLUDE_COMMAND__}%
+ \robExtKeepaftergroup{robExtCompiledIncludeCommand#1}%
+ \robExtKeepaftergroup{l_robExt_placeholder___ROBEXT_COMPILED_#1_INCLUDE_COMMAND___str}%
+ \robExtKeepaftergroup{l_robExt_placeholder___ROBEXT_COMPILED_#1_TEMPLATE___str}%
+ \robExtSaveDependencies{robExtCompiledDependencies#1}%
+ \endgroup%
+ },
+ #1-recompile,
+ #1/.style={
+ disable placeholders,
+ set placeholder={__ROBEXT_LATEX_PREAMBLE__}{},
+ add to preamble/.style={
+ add to placeholder={__ROBEXT_LATEX_PREAMBLE__}{####1},
+ },
+ /utils/exec={\robExtRestoreDependencies{robExtCompiledDependencies#1}},
+ custom include command={\csname robExtCompiledIncludeCommand#1\endcsname},
+ copy placeholder no import={__ROBEXT_TEMPLATE__}{__ROBEXT_COMPILED_#1_TEMPLATE__},
+ copy placeholder no import={__ROBEXT_COMPILATION_COMMAND__}{__ROBEXT_COMPILED_#1_COMPILATION_COMMAND__},
+ __ROBEXT_TMP_CODE_TO_RUN__
+ },%
+ }%
+ }%
+ \robExtRemovePlaceholder{__ROBEXT_TMP_CODE_TO_RUN__}% let us clean our variables
+ \robExtRemovePlaceholder{__ROBEXT_TMP_CODE_TO_COMPILE__}% let us clean our variables
+ },
+ in command/.style={
+ set placeholder={__ROBEXT_MAIN_CONTENT__}{__ROBEXT_MAIN_CONTENT_ORIG__},
+ },
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Interface to change placeholders %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- set placeholder/.code 2 args={\robExtSetPlaceholder{#1}{#2}},
- set main content/.style={
- set placeholder={__ROBEXT_MAIN_CONTENT__}{#1}
+ remove placeholder/.code={\robExtRemovePlaceholder{#1}},
+ remove placeholders/.style={
+ remove placeholder/.list={#1},
+ },
+ set main content/.style={
+ set placeholder={__ROBEXT_MAIN_CONTENT_ORIG__}{#1}
},
copy placeholder/.code 2 args={\robExtCopyPlaceholder{#1}{#2}},
+ copy placeholder no import/.code 2 args={\robExtCopyPlaceholder*{#1}{#2}},
+ set placeholder/.code 2 args={\robExtSetPlaceholder{#1}{#2}},
+ % do not import the placeholder (useful for efficiency reasons)
+ set placeholder no import/.code 2 args={\robExtSetPlaceholder*{#1}{#2}},
+ set placeholder first/.code 2 args={\robExtSetPlaceholderFirst*{#1}{#2}},
set placeholder rec/.code 2 args={\robExtSetPlaceholderRec{#1}{#2}},
+ set placeholder rec keep after group/.code 2 args={\robExtSetPlaceholderRec{#1}{#2}\robExtKeepPlaceholderAfterGroup{#1}},
+ set placeholder rec no import/.code 2 args={\robExtSetPlaceholderRec*{#1}{#2}},
+ set placeholder rec replace from list/.code n args={3}{\robExtSetPlaceholderRecReplaceFromList{#1}{#2}{#3}},
+ set placeholder rec replace from list no import/.code n args={3}{\robExtSetPlaceholderRecReplaceFromList*{#1}{#2}{#3}},
set placeholder eval/.code 2 args={\robExtSetPlaceholderRec{#1}{#2}\robExtEvalPlaceholderInplace{#1}},
+ set placeholder eval no import/.code 2 args={\robExtSetPlaceholderRec*{#1}{#2}\robExtEvalPlaceholderInplace{#1}},
+ set placeholder eval replace from list/.code n args={3}{\robExtSetPlaceholderRecReplaceFromList{#1}{#2}{#3}\robExtEvalPlaceholderInplace{#2}},
+ set placeholder eval replace from list no import/.code n args={3}{\robExtSetPlaceholderRecReplaceFromList*{#1}{#2}{#3}\robExtEvalPlaceholderInplace{#2}},
+ eval placeholder/.code={\robExtEvalPlaceholder{#1}},
+ eval placeholder replace from list/.code 2 args={\robExtEvalPlaceholderReplaceFromList{#1}{#2}},
set placeholder from content/.code 2 args={\robExtPlaceholderFromContent{#1}{#2}},
+ set placeholder from content no import/.code 2 args={\robExtPlaceholderFromContent*{#1}{#2}},
add to placeholder/.code 2 args={\robExtAddToPlaceholder{#1}{#2}},
+ add to placeholder no import/.code 2 args={\robExtAddToPlaceholderNoImport{#1}{#2}},
add to placeholder no space/.code 2 args={\robExtAddToPlaceholder*{#1}{#2}},
+ add to placeholder no space no import/.code 2 args={\robExtAddToPlaceholderNoImport*{#1}{#2}},
add before placeholder/.code 2 args={\robExtAddBeforePlaceholder{#1}{#2}},
add before placeholder no space/.code 2 args={\robExtAddBeforePlaceholder*{#1}{#2}},
+ add before placeholder no import/.code 2 args={\robExtAddBeforePlaceholderNoImport{#1}{#2}},
+ add before placeholder no space no import/.code 2 args={\robExtAddBeforePlaceholderNoImport*{#1}{#2}},
set placeholder path from filename/.code 2 args={\robExtPlaceholderPathFromFilename{#1}{#2}},
+ set placeholder path from filename no import/.code 2 args={\robExtPlaceholderPathFromFilename*{#1}{#2}},
set placeholder from file content/.code 2 args={\robExtPlaceholderFromFileContent{#1}{#2}},
+ set placeholder from file content no import/.code 2 args={\robExtPlaceholderFromFileContent*{#1}{#2}},
set placeholder path from content/.code n args={3}{\robExtPlaceholderPathFromContent{#1}[#3]{#2}},
+ set placeholder path from content no import/.code n args={3}{\robExtPlaceholderPathFromContent*{#1}[#3]{#2}},
eval placeholder in place/.code={\robExtEvalPlaceholderInplace{#1}},
+ placeholder halve number hashes in place/.code={\robExtPlaceholderHalveNumberHashesInplace{#1}},
+ placeholder double number hashes in place/.code={\robExtPlaceholderDoubleNumberHashesInplace{#1}},
+ placeholder replace in place/.code n args={3}{\robExtPlaceholderReplaceInplace{#1}{#2}{#3}},
+ placeholder replace in place eval/.code n args={3}{\robExtPlaceholderReplaceInplaceEval{#1}{#2}{#3}},
% Interface to set template
set template/.style={
- set placeholder={__ROBEXT_TEMPLATE__}{#1},
+ set placeholder first={__ROBEXT_TEMPLATE__}{#1},
+ },
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%% Interface for optimization %%%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % It is important to create an efficient code (otherwise the library can becomes pointless)
+ % and it can help a lot if we give some advices to the system that evaluates placeholders, notably on
+ % the replacement order it should follow:
+ %%%% "only placeholders" says "use only these placeholders in this template/compilation command/... in that order
+ %%%% while "first placeholders" says "start with these placeholders, if it is not enough, continue as usual
+ only placeholders in compilation command/.code={\robExtOnlyPlaceholdersInCompilationCommand{#1}},
+ first placeholders in compilation command/.code={\robExtFirstPlaceholdersInCompilationCommand{#1}},
+ only placeholders in template/.code={\robExtOnlyPlaceholdersInTemplate{#1}},
+ first placeholders in template/.code={\robExtFirstPlaceholdersInTemplate{#1}},
+ only placeholders in include command/.code={\robExtOnlyPlaceholdersInIncludeCommand{#1}},
+ first placeholders in include command/.code={\robExtFirstPlaceholdersInIncludeCommand{#1}},
+ %%%%%%%%%%%%%
+ %%% Debug %%%
+ %%%%%%%%%%%%%
+ more logs/.code={\def\robExtDebugMessage#1{\message{^^J[robExt] #1}}},
+ less logs/.code={\def\robExtDebugMessage#1{}},
+ show placeholder/.code={\robExtShowPlaceholder{#1}},
+ show placeholders/.code={\robExtShowPlaceholders},
+ show placeholders contents/.code={\robExtShowPlaceholdersContents},
+ print imported placeholders except default/.code={\robExtPrintAllPlaceholdersExceptDefaults},
+ print imported placeholders/.code={\robExtPrintAllPlaceholders},
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%% Optimizations %%%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ do not load special placeholders/.code={\let\robExtDoNotLoadSpecialPlaceholders\undefined},
+ load special placeholders/.code={\def\robExtDoNotLoadSpecialPlaceholders{}},
+ do not load special placeholders,
+ %% Replace very little placeholders, basically only __ROBEXT_MAIN_CONTENT__, __ROBEXT_MAIN_CONTENT_ORIG__,
+ %% and the default (prefix, source, output, wayback, cache folder)
+ disable placeholders/.code={\def\robExtDisablePlaceholders{}},
+ enable placeholders/.code={\let\robExtDisablePlaceholders\undefined},
+ %% If all placeholders have __, this option will speed up the compilation time
+ all placeholders have underscores/.code={\def\robExtPlaceholderOnlyWithUnderscores{}},
+ not all placeholders have underscores/.code={\let\robExtPlaceholderOnlyWithUnderscores\undefined},
+ %% not sure if I want users to disable import mechanism as they might use dirty things
+ enable import mechanism/.code={\def\robExtEnableImportMechanism{}},
+ disable import mechanism/.code={\let\robExtEnableImportMechanism\undefined},
+ disable optimizations/.style={
+ not all placeholders have underscores,
+ disable import mechanism,
+ },
+ enable optimizations/.style={
+ all placeholders have underscores,
+ enable import mechanism,
+ },
+ enable optimizations,
+ %%%%%%%%%%%%%%
+ %%% Groups %%%
+ %%%%%%%%%%%%%%
+ clear imported placeholders/.code={\robExtClearImportedPlaceholders},
+ remove imported placeholder/.code={\robExtRemoveImportedPlaceholder{#1}},
+ remove imported placeholders/.style={
+ remove imported placeholder/.list={#1},
},
+ print group placeholders/.code={\robExtPrintGroupPlaceholders{#1}},
+ new group placeholders/.code={\robExtRegisterGroupPlaceholders{#1}},
+ add placeholder to group/.code 2 args={\robExtAddPlaceholdersToGroup{#1}{#2}},
+ add placeholders to group/.code 2 args={\robExtAddPlaceholdersToGroup{#1}{#2}},
+ remove placeholder from group/.code 2 args={\robExtRemovePlaceholdersFromGroup{#1}{#2}},
+ remove placeholders from group/.code 2 args={\robExtRemovePlaceholdersFromGroup{#1}{#2}},
+ copy group placeholders/.code 2 args={\robExtCopyGroupPlaceholders{#1}{#2}},
+ append group placeholders/.code 2 args={\robExtAppendGroupPlaceholders{#1}{#2}},
+ append before group placeholders/.code 2 args={\robExtAppendGroupPlaceholders{#1}{#2}},
+ import placeholders from group/.code={\robExtImportPlaceholdersFromGroup{#1}},
+ import all placeholders/.code={\robExtImportAllPlaceholders},
+ % ok this is a different kind of group, here latex group { }
+ import placeholder/.code={\robExtImportPlaceholder{#1}},
+ import all placeholders/.code={\robExtImportAllPlaceholders},
+ import placeholders/.style={
+ import placeholder/.list={#1},
+ },
+ import placeholder first/.code={\robExtImportPlaceholderFirst{#1}},
+ import placeholders first/.code={\robExtAddPlaceholdersToListFirst{#1}},
+ import placeholders from group/.code={\robExtImportPlaceholdersFromGroup{#1}},
+ print all registered groups/.code={\robExtPrintAllRegisteredGroups},
+ print all registered groups and placeholders/.code={\robExtPrintAllRegisteredGroupsAndPlaceholders},
+ show all registered groups/.code={\robExtShowAllRegisteredGroupsAndPlaceholders},
+ show all registered groups and placeholders/.code={\robExtShowAllRegisteredGroupsAndPlaceholders},
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Configure dependencies %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -781,7 +1805,11 @@ if __name__ == '__main__':
reset dependencies/.code={\robExtResetDependencies{}},
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Compilation command %%%
- %%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % People might want to force the compilation even if shell_unrestricted is false, notably if they
+ % allow commands like mkdir/cd/pdflatex to run in restricted mode.
+ force compilation/.code={\def\robExtForceCompilation{}},
+ do not force compilation/.code={\let\robExtForceCompilation\undefined},
set compilation command/.code={\robExtSetCompilationCommand{#1}},
add argument to compilation command/.code={\robExtAddArgumentToCompilationCommand{#1}},
add arguments to compilation command/.style={
@@ -818,6 +1846,8 @@ if __name__ == '__main__':
%% reasons, you can use these commands and run the command manually later):
enable manual mode/.code={\def\robExtManualMode{}},
disable manual mode/.code={\let\robExtManualMode\undefined},
+ enable fallback to manual mode/.code={\def\robExtFallbackManualMode{}},
+ disable fallback to manual mode/.code={\let\robExtFallbackManualMode\undefined},
%% Arguments to include graphics
include graphics args/.code={\def\robExtIncludeGraphicsArgs{#1}},
%% The role of this command is to set \l_robExt_result_str, that will contain the final string.
@@ -828,7 +1858,10 @@ if __name__ == '__main__':
set filename prefix/.code={\def\robExtPrefixFilename{#1}},
% first argument is subfolder, second is how to get from subfolder to the folder containing the source:
% set subfolder and way back={robustExternal/}{../}
+ % synonyme, "cache folder" is prefered over ""
set subfolder and way back/.code 2 args={\def\robExtCacheFolder{#1}\def\robExtCacheFolderWayBack{#2}},
+ set cache folder and way back/.code 2 args={\def\robExtCacheFolder{#1}\def\robExtCacheFolderWayBack{#2}},
+ no cache folder/.code={\let\robExtCacheFolder\undefined\def\robExtCacheFolderWayBack{}},
% By default we put everything in robustExternalize
% Change this before starting to cache any library, and if you change it mid-document, be aware
% that you will not be able to refer to elements in the old folder.
@@ -839,6 +1872,7 @@ if __name__ == '__main__':
%% Note: this does not work reliably for now
%% TODO: fix this!
disable externalization/.code={\def\robExtDisableExternalization{}},
+ disable externalization now/.code={\robExtDisableTikzpictureOverwrite\def\robExtDisableExternalization{}},
enable externalization/.code={\let\robExtDisableExternalization\undefined},
% Useful to wrap, for instance, text
command if no externalization/.code={\robExtDisableTikzpictureOverwrite\evalPlaceholder{__ROBEXT_MAIN_CONTENT__}},
@@ -861,30 +1895,22 @@ if __name__ == '__main__':
%%% \blenderpointNamedOutputFilenameVideoA containing thehashthatisusedforthename
%%% \blenderpointNamedOutputPrVideoA containing thehashthatisusedforthename
%% See \robExtGetNamedOutputFilename to get them with \robExtGetNamedOutputFullPath
- % name output/.style={name output with ext={#1}{.pdf}},
- % name input/.style={name output with ext={#1}{.tex}},
- % % like name output but adds the extension like name output with ext={VideoA}{.mp4}
- % name output with ext/.code 2 args={%
- % \robExtSetPlaceholder{__#1__}{\robExtPrefixFilename\robExtFinalHash#2}
- % \robExtEvalPlaceholderInplace{__#1__}
- % \robExtSetPlaceholder{__#1_FULL_PATH__}{\robExtAddCachePathAndName{\robExtFinalHash#2}}
- % \robExtEvalPlaceholderInplace{__#1_FULL PATH__}
- % },
name output/.code={%
\def\robExtExecuteNamedOutput{%
\expandafter\xdef\csname #1\endcsname{\robExtPrefixFilename\robExtFinalHash}%
\expandafter\xdef\csname #1InCache\endcsname{\robExtAddCachePathAndName{\robExtFinalHash}}%
}%
},
- %% Todo: for this to work, be will need to make the definition either global (not trivial, need to define
- %% a new list of global placeholders), or at least go past the groups
}
% Not really made for the end user
% It assumes that __ROBEXT_COMPILATION_COMMAND__ and __ROBEXT_TEMPLATE__ is set
\NewDocumentCommand{\robExtEvaluateCompileAndInclude}{}{%
\ifdefined\robExtDisableExternalization%
- \pgfkeys{/robExt/.cd,command if no externalization}%
+ \pgfkeys{
+ /robExt/.cd,
+ command if no externalization,
+ }%
\else%
\ifdefined\robExtExecuteBefore\robExtExecuteBefore\fi%
\robExtWriteFile{}%
@@ -893,14 +1919,16 @@ if __name__ == '__main__':
\ifdefined\robExtExecuteNamedOutput\robExtExecuteNamedOutput\fi%
\ifdefined\robExtExecuteAfter\robExtExecuteAfter\fi%
\fi%
+ \message{Finished to include the file.}%
}
+
%% #1: Arguments, #2: content to externalize
\NewDocumentCommand{\robExtCacheMe}{O{}m}{%
{% Group
\pgfkeys{%
/robExt/.cd,
- set placeholder={__ROBEXT_MAIN_CONTENT__}{#2},
+ set placeholder={__ROBEXT_MAIN_CONTENT_ORIG__}{#2},
default style,
#1,
}%
@@ -910,10 +1938,6 @@ if __name__ == '__main__':
\let\cacheMe\robExtCacheMe
%% #1: Arguments, #2: content to externalize
-% \NewDocumentEnvironment{robExtern}{O{}+b}{%
-% \robExt[#1]{#2}%
-% }{}
-
\NewDocumentEnvironment{RobExtCacheMe}{m+b}{%
\robExtCacheMe[#1]{#2}%
}{}
@@ -921,7 +1945,7 @@ if __name__ == '__main__':
\let\endCacheMe\endRobExtCacheMe
\NewDocumentEnvironment{RobExtCacheMeCode}{m}{%
- \RobExtPlaceholderFromCode{__ROBEXT_MAIN_CONTENT__}%
+ \RobExtPlaceholderFromCode{__ROBEXT_MAIN_CONTENT_ORIG__}%
}{%
\endRobExtPlaceholderFromCode%
\pgfkeys{%
@@ -939,89 +1963,105 @@ if __name__ == '__main__':
\let\CacheMeNoContent\RobExtCacheMeNoContent
\let\endCacheMeNoContent\endRobExtCacheMeNoContent
-\NewDocumentCommand{\robExtConfigure}{m}{%
- \pgfkeys{
- /robExt/.cd,#1%Do not add a space before the #1!
- }%
-}
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%% Default presets %%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% We create here a few presets and placeholders useful later
-%%%% Available in all styles
-\robExtConfigure{
- set includegraphics options/.style={
- set placeholder={__ROBEXT_INCLUDEGRAPHICS_OPTIONS__}{#1},
- },
- add to includegraphics options/.style={
- add to placeholder no space={__ROBEXT_INCLUDEGRAPHICS_OPTIONS__}{,#1},
- },
- set placeholder={__ROBEXT_VERBATIM_COMMAND__}{\verbatiminput},
- % We expect the program to write in __ROBEXT_OUTPUT_PREFIX__-out.txt
- verbatim output/.style={
- custom include command={%
- \evalPlaceholder{%
- __ROBEXT_VERBATIM_COMMAND__{__ROBEXT_CACHE_FOLDER____ROBEXT_OUTPUT_PREFIX__-out.txt}%
- }%
- },
- }
-}
-
-%%%% For LaTeX codes
+%%%%%%
+%%%%%% Group "special characters"
+%%%%%%
-\setPlaceholder{__ROBEXT_LATEX_OPTIONS__}{}
-\setPlaceholder{__ROBEXT_DOCUMENT_CLASS__}{standalone}
-\setPlaceholder{__ROBEXT_PREAMBLE__}{}
-\setPlaceholder{__ROBEXT_INCLUDEGRAPHICS_OPTIONS__}{}
-\setPlaceholder{__ROBEXT_INCLUDEGRAPHICS_FILE__}{\robExtAddCachePathAndName{\robExtFinalHash.pdf}}
-\setPlaceholder{__ROBEXT_LATEX_TRIM_LENGTH__}{30cm}
-
-\begin{PlaceholderFromCode}{__ROBEXT_LATEX__}
-\documentclass[__ROBEXT_LATEX_OPTIONS__]{__ROBEXT_DOCUMENT_CLASS__}
-__ROBEXT_PREAMBLE__
+%%%% Generic placeholders, practical to escape stuff
+\robExtClearGroupPlaceholders{main}
+\ExplSyntaxOn
+\robExtPlaceholderFromString{__ROBEXT_LEFT_BRACE__}{\c_left_brace_str}
+\robExtPlaceholderFromString{__ROBEXT_RIGHT_BRACE__}{\c_right_brace_str}
+\robExtPlaceholderFromString{__ROBEXT_BACKSLASH__}{\c_backslash_str}
+\robExtPlaceholderFromString{__ROBEXT_HASH__}{\c_hash_str}
+\robExtPlaceholderFromString{__ROBEXT_PERCENT__}{\c_percent_str}
+\robExtPlaceholderFromString{__ROBEXT_UNDERSCORE__}{\c_underscore_str}
+\ExplSyntaxOff
+\robExtCopyGroupPlaceholders{special characters}{main}
+\robExtRegisterGroupPlaceholders{special characters}
+
+%%%%%%
+%%%%%% Group "latex"
+%%%%%%
+
+\robExtClearGroupPlaceholders{main}
+
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_LATEX__}
+\documentclass[__ROBEXT_LATEX_OPTIONS__]{__ROBEXT_LATEX_DOCUMENT_CLASS__}
+__ROBEXT_LATEX_PREAMBLE__
+% most packages must be loaded before hyperref
+% so we typically want to load hyperref here
+__ROBEXT_LATEX_PREAMBLE_HYPERREF__
+% some packages must be loaded after hyperref
+__ROBEXT_LATEX_PREAMBLE_AFTER_HYPERREF__
\begin{document}%
-__ROBEXT_MAIN_CONTENT_WRAPPED__
+__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__
\end{document}
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
-\begin{PlaceholderFromCode}{__ROBEXT_MAIN_CONTENT_WRAPPED__}
-__ROBEXT_CREATE_OUT_FILE__%
+\robExtSetPlaceholder{__ROBEXT_LATEX_OPTIONS__}{}
+\robExtSetPlaceholder{__ROBEXT_LATEX_DOCUMENT_CLASS__}{standalone}
+\robExtSetPlaceholder{__ROBEXT_LATEX_PREAMBLE__}{}
+\robExtSetPlaceholder{__ROBEXT_LATEX_PREAMBLE_HYPERREF__}{}
+\robExtSetPlaceholder{__ROBEXT_LATEX_PREAMBLE_AFTER_HYPERREF__}{}
+\robExtSetPlaceholder{__ROBEXT_LATEX_TRIM_LENGTH__}{30cm}
+
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__}
+__ROBEXT_LATEX_CREATE_OUT_FILE__%
\newsavebox\boxRobExt%
-\savebox{\boxRobExt}{%
+\begin{lrbox}{\boxRobExt}%
__ROBEXT_MAIN_CONTENT__%
-}%
+\end{lrbox}%
\usebox{\boxRobExt}%
-__ROBEXT_WRITE_DEPTH_TO_OUT_FILE__%
-\end{PlaceholderFromCode}
+__ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__%
+\end{RobExtPlaceholderFromCode}
-\begin{PlaceholderFromCode}{__ROBEXT_CREATE_OUT_FILE__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_LATEX_CREATE_OUT_FILE__}
%% We save the height/depth of the content by using a savebox:
\newwrite\writeRobExt%
\immediate\openout\writeRobExt=\jobname-out.tex%
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
-\begin{PlaceholderFromCode}{__ROBEXT_WRITE_DEPTH_TO_OUT_FILE__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__}
\immediate\write\writeRobExt{%
\string\def\string\robExtWidth{\the\wd\boxRobExt}%
\string\def\string\robExtHeight{\the\ht\boxRobExt}%
\string\def\string\robExtDepth{\the\dp\boxRobExt}%
}%
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
%% Compilation commands
-\setPlaceholder{__ROBEXT_COMPILATION_COMMAND_LATEX__}{__ROBEXT_LATEX_ENGINE__ __ROBEXT_COMPILATION_COMMAND_OPTIONS__ "__ROBEXT_SOURCE_FILE__"}
-\setPlaceholder{__ROBEXT_COMPILATION_COMMAND_OPTIONS__}{-shell-escape -halt-on-error}
-\setPlaceholder{__ROBEXT_LATEX_ENGINE__}{pdflatex}
+\robExtSetPlaceholder{__ROBEXT_LATEX_COMPILATION_COMMAND__}{__ROBEXT_LATEX_ENGINE__ __ROBEXT_LATEX_COMPILATION_COMMAND_OPTIONS__ "__ROBEXT_SOURCE_FILE__"}
+\robExtSetPlaceholder{__ROBEXT_LATEX_COMPILATION_COMMAND_OPTIONS__}{-halt-on-error}
+\robExtSetPlaceholder{__ROBEXT_LATEX_ENGINE__}{pdflatex}
\robExtConfigure{
+ %%%% Allow users to specify which command to try (or try first) when replacing placeholders. Order matters.
+ %%%% it looks ugly, but it is mostly for performance improvements.
+ first placeholders latex/.style={
+ first placeholders in compilation command={__ROBEXT_LATEX_COMPILATION_COMMAND__,__ROBEXT_LATEX_ENGINE__,__ROBEXT_LATEX_COMPILATION_COMMAND_OPTIONS__},
+ first placeholders in template={__ROBEXT_LATEX__,__ROBEXT_LATEX_OPTIONS__,__ROBEXT_LATEX_DOCUMENT_CLASS__,__ROBEXT_LATEX_PREAMBLE__,__ROBEXT_LATEX_PREAMBLE_HYPERREF__,__ROBEXT_LATEX_PREAMBLE_AFTER_HYPERREF__,__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__,__ROBEXT_LATEX_TRIM_LENGTH__,__ROBEXT_LATEX_CREATE_OUT_FILE__,__ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__,__ROBEXT_MAIN_CONTENT__,__ROBEXT_MAIN_CONTENT_ORIG__},
+ },
+ only placeholders latex/.style={
+ only placeholders in compilation command={__ROBEXT_LATEX_COMPILATION_COMMAND__,__ROBEXT_LATEX_ENGINE__,__ROBEXT_LATEX_COMPILATION_COMMAND_OPTIONS__},
+ only placeholders in template={__ROBEXT_LATEX__,__ROBEXT_LATEX_OPTIONS__,__ROBEXT_LATEX_DOCUMENT_CLASS__,__ROBEXT_LATEX_PREAMBLE__,__ROBEXT_LATEX_PREAMBLE_HYPERREF__,__ROBEXT_LATEX_PREAMBLE_AFTER_HYPERREF__,__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__,__ROBEXT_LATEX_TRIM_LENGTH__,__ROBEXT_LATEX_CREATE_OUT_FILE__,__ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__,__ROBEXT_MAIN_CONTENT__,__ROBEXT_MAIN_CONTENT_ORIG__},
+ },
% some useful presets
latex/.style={
+ enable placeholders,
+ % This way it appears before orig in the list: more efficient
+ import placeholders from group={latex},
+ set placeholder={__ROBEXT_MAIN_CONTENT__}{__ROBEXT_MAIN_CONTENT_ORIG__},
+ import placeholder={__ROBEXT_MAIN_CONTENT_ORIG__},
+ first placeholders latex,
set template={__ROBEXT_LATEX__},
- set compilation command={__ROBEXT_COMPILATION_COMMAND_LATEX__},
+ set compilation command={__ROBEXT_LATEX_COMPILATION_COMMAND__},
%% Configure the latex compilation engine
use latexmk/.style={
set placeholder={__ROBEXT_LATEX_ENGINE__}{latexmk},
@@ -1039,16 +2079,34 @@ __ROBEXT_WRITE_DEPTH_TO_OUT_FILE__%
add to placeholder no space={__ROBEXT_LATEX_OPTIONS__}{,##1},
},
set documentclass/.style={
- set placeholder={__ROBEXT_DOCUMENT_CLASS__}{##1},
+ set placeholder={__ROBEXT_LATEX_DOCUMENT_CLASS__}{##1},
},
set preamble/.style={
- set placeholder={__ROBEXT_PREAMBLE__}{##1},
+ set placeholder={__ROBEXT_LATEX_PREAMBLE__}{##1},
},
add to preamble/.style={
- add to placeholder={__ROBEXT_PREAMBLE__}{##1},
+ add to placeholder={__ROBEXT_LATEX_PREAMBLE__}{##1},
+ },
+ add before main content/.style={
+ add before placeholder no space={__ROBEXT_MAIN_CONTENT__}{##1},
+ },
+ add before preamble/.style={
+ add before placeholder={__ROBEXT_LATEX_PREAMBLE__}{##1},
+ },
+ set preamble hyperref/.style={
+ set placeholder={__ROBEXT_LATEX_PREAMBLE_HYPERREF__}{##1},
+ },
+ add to preamble hyperref/.style={
+ add to placeholder={__ROBEXT_LATEX_PREAMBLE_HYPERREF__}{##1},
+ },
+ set preamble after hyperref/.style={
+ set placeholder={__ROBEXT_LATEX_PREAMBLE_AFTER_HYPERREF__}{##1},
+ },
+ add to preamble after hyperref/.style={
+ add to placeholder={__ROBEXT_LATEX_PREAMBLE_AFTER_HYPERREF__}{##1},
},
do not wrap code/.style={
- set placeholder={__ROBEXT_MAIN_CONTENT_WRAPPED__}{__ROBEXT_MAIN_CONTENT__},
+ set placeholder={__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__}{__ROBEXT_MAIN_CONTENT__},
},
add to includegraphics options={trim=__ROBEXT_LATEX_TRIM_LENGTH__ __ROBEXT_LATEX_TRIM_LENGTH__ __ROBEXT_LATEX_TRIM_LENGTH__ __ROBEXT_LATEX_TRIM_LENGTH__},
add to latex options={margin=__ROBEXT_LATEX_TRIM_LENGTH__},
@@ -1056,25 +2114,36 @@ __ROBEXT_WRITE_DEPTH_TO_OUT_FILE__%
set placeholder={__ROBEXT_LATEX_TRIM_LENGTH__}{0cm}
},
},
+ % U
tikz/.style={
latex,
add to preamble={\usepackage{tikz}},
- add before placeholder no space={__ROBEXT_MAIN_CONTENT__}{\begin{tikzpicture}},
- add to placeholder no space={__ROBEXT_MAIN_CONTENT__}{\end{tikzpicture}},
+ },
+ tikzpicture/.style={
+ tikz,
+ set placeholder no import={__ROBEXT_MAIN_CONTENT__}{\begin{tikzpicture}__ROBEXT_MAIN_CONTENT_ORIG__\end{tikzpicture}},
},
}
-% %%%%%%% Integration with python
+\robExtCopyGroupPlaceholders{latex}{main}
+\robExtRegisterGroupPlaceholders{latex}
+
+
+%%%%%%
+%%%%%% Group "python"
+%%%%%%
+
+\robExtClearGroupPlaceholders{main}
-\begin{PlaceholderFromCode}{__ROBEXT_PYTHON__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_PYTHON__}
__ROBEXT_PYTHON_IMPORT__
__ROBEXT_PYTHON_MAIN_CONTENT_WRAPPED__
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
-\setPlaceholder{__ROBEXT_PYTHON_IMPORT__}{}
+\robExtSetPlaceholder{__ROBEXT_PYTHON_IMPORT__}{}
-\begin{PlaceholderFromCode}{__ROBEXT_PYTHON_MAIN_CONTENT_WRAPPED__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_PYTHON_MAIN_CONTENT_WRAPPED__}
# This file will be loaded in latex. Useful to pass data to the main document
f_out_write = open("__ROBEXT_OUTPUT_PREFIX__-out.tex", "w")
@@ -1147,19 +2216,21 @@ __ROBEXT_MAIN_CONTENT__
### Ending main content
__ROBEXT_PYTHON_FINISHED_WITH_NO_ERROR__
f_out_write.close()
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
% It is annoying to manually call finished_with_no_error(), but it is handy to be able to disable it.
-\begin{PlaceholderFromCode}{__ROBEXT_PYTHON_FINISHED_WITH_NO_ERROR__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_PYTHON_FINISHED_WITH_NO_ERROR__}
finished_with_no_error()
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
%% On windows, python3 does not exist, and python points to python3. On linux, it seems to depend, at least on
%% my system it points to python3 as well.
-\setPlaceholder{__ROBEXT_PYTHON_EXEC__}{python}
+\robExtSetPlaceholder{__ROBEXT_PYTHON_EXEC__}{python}
\robExtConfigure{
python/.style={
+ enable placeholders,
+ import placeholders={__ROBEXT_PYTHON__,__ROBEXT_PYTHON_IMPORT__,__ROBEXT_PYTHON_MAIN_CONTENT_WRAPPED__,__ROBEXT_PYTHON_FINISHED_WITH_NO_ERROR__,__ROBEXT_PYTHON_EXEC__},
set compilation command={__ROBEXT_PYTHON_EXEC__ "__ROBEXT_SOURCE_FILE__"},
set template={__ROBEXT_PYTHON__},
print verbatim if no externalization,
@@ -1169,8 +2240,18 @@ finished_with_no_error()
}
}
+\robExtCopyGroupPlaceholders{python}{main}
+\robExtRegisterGroupPlaceholders{python}
+
+
+%%%%%%
+%%%%%% Group "python print code result"
+%%%%%%
+
+\robExtClearGroupPlaceholders{main}
+
%% A style to print both the code and the result:
-\begin{PlaceholderFromCode}{__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_BEFORE__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_BEFORE__}
# File where print("bla") should be redirected
# get_filename_from_extension("-foo.txt") will give you the path of the file
# in the cache that looks like robExt-somehash-foo.txt
@@ -1195,20 +2276,23 @@ with open(get_filename_from_extension("-code.txt"), "w") as f:
if should_write:
f.write(line)
### CODESTARTSHERE
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
-\begin{PlaceholderFromCode}{__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_AFTER__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_AFTER__}
### CODESTOPSHERE
print_file.close()
-\end{PlaceholderFromCode}
-\setPlaceholder{__ROBEXT_PYTHON_TCOLORBOX_PROPS__}{colback=red!5!white,colframe=red!75!black}
-\setPlaceholder{__ROBEXT_PYTHON_CODE_MESSAGE__}{}
-\setPlaceholder{__ROBEXT_PYTHON_RESULT_MESSAGE__}{Output:}
-\setPlaceholder{__ROBEXT_PYTHON_LSTINPUT_STYLE__}{frame=single, breakindent=.5\textwidth, frame=single, breaklines=true, style=mypython}
+\end{RobExtPlaceholderFromCode}
+
+\robExtSetPlaceholder{__ROBEXT_PYTHON_TCOLORBOX_PROPS__}{colback=red!5!white,colframe=red!75!black}
+\robExtSetPlaceholder{__ROBEXT_PYTHON_CODE_MESSAGE__}{}
+\robExtSetPlaceholder{__ROBEXT_PYTHON_RESULT_MESSAGE__}{Output:}
+\robExtSetPlaceholder{__ROBEXT_PYTHON_LSTINPUT_STYLE__}{frame=single, breakindent=.5\textwidth, frame=single, breaklines=true, style=mypython}
+
\robExtConfigure{
python print code and result/.style={
python,
+ import placeholders={__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_BEFORE__,__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_AFTER__,__ROBEXT_PYTHON_TCOLORBOX_PROPS__,__ROBEXT_PYTHON_CODE_MESSAGE__,__ROBEXT_PYTHON_RESULT_MESSAGE__,__ROBEXT_PYTHON_LSTINPUT_STYLE__},
add before placeholder no space={__ROBEXT_MAIN_CONTENT__}{__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_BEFORE__},
add to placeholder no space={__ROBEXT_MAIN_CONTENT__}{__ROBEXT_PYTHON_PRINT_CODE_RESULT_TEMPLATE_AFTER__},
set title/.style={
@@ -1229,11 +2313,19 @@ print_file.close()
},
}
+\robExtCopyGroupPlaceholders{python print code result}{main}
+\robExtRegisterGroupPlaceholders{python print code result}
+
-%%%% Verbatim text
+%%%%%%
+%%%%%% Group "verbatim"
+%%%%%%
+
+\robExtClearGroupPlaceholders{main}
\robExtConfigure{
verbatim text/.style={
+ enable placeholders,
set template={__ROBEXT_MAIN_CONTENT__},
custom include command={\evalPlaceholder{\verbatiminput{\robExtAddCachePathAndName{\robExtFinalHash.tex}}}},
%% Apparently this works on windows as well https://stackoverflow.com/questions/1702762/how-can-i-create-an-empty-file-at-the-command-line-in-windows
@@ -1248,9 +2340,17 @@ print_file.close()
},
}
-%%%%% Bash
+\robExtCopyGroupPlaceholders{verbatim}{main}
+\robExtRegisterGroupPlaceholders{verbatim}
+
+
+%%%%%%
+%%%%%% Group "bash"
+%%%%%%
+
+\robExtClearGroupPlaceholders{main}
-\begin{PlaceholderFromCode}{__ROBEXT_BASH_TEMPLATE__}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_BASH_TEMPLATE__}
# Quit if there is an error
set -e
outputTxt="__ROBEXT_OUTPUT_PREFIX__-out.txt"
@@ -1259,44 +2359,278 @@ outputPdf="__ROBEXT_OUTPUT_PDF__"
__ROBEXT_MAIN_CONTENT__
# Create the pdf file to certify that no compilation error occured
touch "${outputPdf}"
-\end{PlaceholderFromCode}
+\end{RobExtPlaceholderFromCode}
-\setPlaceholder{__ROBEXT_BASH_SHELL__}{bash}
+\robExtSetPlaceholder{__ROBEXT_BASH_SHELL__}{bash}
\robExtConfigure{
bash/.style={
+ enable placeholders,
+ import placeholders={__ROBEXT_BASH_TEMPLATE__,__ROBEXT_BASH_SHELL__},
set compilation command={__ROBEXT_BASH_SHELL__ "__ROBEXT_SOURCE_FILE__"},
set template={__ROBEXT_BASH_TEMPLATE__},
print verbatim if no externalization,
}
}
+\robExtCopyGroupPlaceholders{bash}{main}
+\robExtRegisterGroupPlaceholders{bash}
-%%%%% Replace tikzpicture:
+%%%%%%
+%%%%%% Group "default", available in all styles
+%%%%%%
-\NewDocumentCommand{\robExtExternalizeAllTikzpictures}{}{%
- %% We need to save the tikzpicture environment to avoid infinite recursion if we disable externalization
- \let\robExtTikzPictureOrig\tikzpicture%
- \let\endrobExtTikzPictureOrig\endtikzpicture%
- \DeclareDocumentEnvironment{tikzpicture}{O{}O{}b}{%
- \begin{CacheMe}{tikz,##2}[##1]%
- ##3%
- \end{CacheMe}%
- }{}%
+\robExtClearGroupPlaceholders{main}
+
+% This additional level of indirection is made to allow an easier wrapping
+% of \begin{tikzpicture} ... \end{tikzpicture} for instance.
+% The original behavior (modify __ROBEXT_MAIN_CONTENT__ directly)
+% was not really practical as if you use both |tikz| and |\cacheCommand|, it would wrap
+% the environment twice.
+\robExtSetPlaceholder{__ROBEXT_MAIN_CONTENT__}{__ROBEXT_MAIN_CONTENT_ORIG__}
+\setPlaceholder{__ROBEXT_INCLUDEGRAPHICS_OPTIONS__}{}
+\setPlaceholder{__ROBEXT_INCLUDEGRAPHICS_FILE__}{\robExtAddCachePathAndName{\robExtFinalHash.pdf}}
+
+\robExtConfigure{
+ % Allow nice optimizations
+ all placeholders have underscores,
+ set includegraphics options/.style={
+ set placeholder no import={__ROBEXT_INCLUDEGRAPHICS_OPTIONS__}{#1},
+ },
+ add to includegraphics options/.style={
+ add to placeholder no space no import={__ROBEXT_INCLUDEGRAPHICS_OPTIONS__}{,#1},
+ },
+ set placeholder no import={__ROBEXT_VERBATIM_COMMAND__}{\verbatiminput},
+ % We expect the program to write in __ROBEXT_OUTPUT_PREFIX__-out.txt
+ verbatim output/.style={
+ import placeholders={__ROBEXT_VERBATIM_COMMAND__},
+ custom include command={%
+ \evalPlaceholder{%
+ __ROBEXT_VERBATIM_COMMAND__{__ROBEXT_CACHE_FOLDER____ROBEXT_OUTPUT_PREFIX__-out.txt}%
+ }%
+ },
+ },
+ % Mostly for debugging purpose
+ print command and source/.style={
+ enable manual mode,
+ custom include command advanced={%
+ \evalPlaceholder{%
+ Command: (run in folder \texttt{__ROBEXT_CACHE_FOLDER__})
+ \robExtPrintPlaceholder{__ROBEXT_COMPILATION_COMMAND__}
+ Dependencies:
+ \verbatiminput{__ROBEXT_CACHE_FOLDER____ROBEXT_OUTPUT_PREFIX__.deps}%
+ Source (in \texttt{__ROBEXT_CACHE_FOLDER____ROBEXT_OUTPUT_PREFIX__.tex}):
+ \verbatiminput{__ROBEXT_CACHE_FOLDER____ROBEXT_OUTPUT_PREFIX__.tex}%
+ }%
+ },
+ },
+ debug/.style={
+ print command and source
+ },
}
-% To avoid infinite recursion when using \robExtExternalizeAllTikzpictures, we need to redefine tikzpicture
-\NewDocumentCommand{\robExtDisableTikzpictureOverwrite}{}{%
- \ifdefined\robExtTikzPictureOrig%
- \let\tikzpicture\robExtTikzPictureOrig%
- \let\endtikzpicture\endrobExtTikzPictureOrig%
- \fi%
+
+\robExtCopyGroupPlaceholders{default}{main} % we do not reset it as it will be the default imported group
+\robExtRegisterGroupPlaceholders{default}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%% Automatically cache environments, tikzpicture etc %%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%
+%%%%%% Parse tikz
+%%%%%%
+
+%% The parser is mostly taken from
+%% https://github.com/sasozivanovic/memoize/blob/master/memoize-tikz.tex
+
+\newtoks\robExt@temptoks
+\def\robExt@apptotoks#1#2{\expandafter#1\expandafter{\the#1#2}}
+
+\def\robExt@tikz{%
+ \robExt@temptoks={}%
+ \robExt@tikz@anim%
+}
+\def\robExt@tikz@anim{%
+ \pgfutil@ifnextchar[{\robExt@tikz@opt}{%
+ \pgfutil@ifnextchar:{\robExt@tikz@anim@a}{%
+ \robExt@tikz@code}}%]
+}%
+\def\robExt@tikz@anim@a#1=#2{%
+ \robExt@apptotoks\robExt@temptoks{#1={#2}}%
+ \robExt@tikz@anim%
+}%
+\def\robExt@tikz@opt[#1]{%
+ \robExt@apptotoks\robExt@temptoks{[#1]}%
+ \robExt@tikz@code%
+}
+\def\robExt@tikz@code{%
+ \pgfutil@ifnextchar\bgroup\robExt@tikz@braced\robExt@tikz@single%
+}
+\def\robExt@tikz@braced#1{\robExt@apptotoks\robExt@temptoks{{#1}}\robExt@tikz@done}
+\def\robExt@tikz@single#1;{\robExt@apptotoks\robExt@temptoks{#1;}\robExt@tikz@done}
+\def\robExt@tikz@done{%
+ \edef\robExt@marshal{%
+ \noexpand\robExtRescanHashRobust{\noexpand\robExtCacheMe[\expandonce{\robExt@tmp@orig@args}, \expandonce{\robExt@tmp@args}]{%
+ \noexpand\tikz\the\robExt@temptoks%
+ }%
+ }%
+ }%
+ \robExt@marshal%
}
+\NewDocumentCommand{\robExtExternalizeAllTikzpictures}{O{tikz}O{tikzpicture}O{<>}}{%
+ \robExtCacheEnvironment[#3]{#2}{tikzpicture}%
+ % Tikz has a more complicated parsing system
+ \DeclareCommandCopy{\robExtCommandOrigtikz}{\tikz}% we save the function for later reset
+ \robExtAddToCommandResetList{tikz}% we add it to the list of functions to reset
+ \DeclareDocumentCommand{\tikz}{D#3{}}{%
+ \def\robExtCommandOrigName{tikz}% we specify the name of the current environment
+ \edef\robExt@tmp@args{\detokenize{##1}}% we specify the name of the current environment
+ \edef\robExt@tmp@orig@args{\detokenize{#1}}% we specify the name of the current environment
+ % we start the parsing
+ \robExt@tikz%
+ }%
+}
+\let\cacheTikz\robExtExternalizeAllTikzpictures
+
+% \NewDocumentCommand{\robExtExternalizeAllTikzpictures}{O{<>}O{tikz}O{tikzpicture}}{%
+% \robExtCacheEnvironment[#1]{#3}{tikzpicture}%
+% % \robExtCacheCommand[#1]{tikz}[O{}m]{tikz}
+% % Tikz has a more complicated parsing system
+% \DeclareCommandCopy{\robExtCommandOrigtikz}{\tikz}% we save the function for later reset
+% \robExtAddToCommandResetList{tikz}% we add it to the list of functions to reset
+% \DeclareDocumentCommand{\tikz}{D#1{}}{%
+% \def\robExtCommandOrigName{tikz}% we specify the name of the current environment
+% \edef\robExt@tmp@args{\detokenize{##1}}% we specify the name of the current environment
+% \edef\robExt@tmp@orig@args{\detokenize{#2}}% we specify the name of the current environment
+% % we start the parsing
+% \robExt@tikz%
+% }%
+% }
+% \let\cacheTikz\robExtExternalizeAllTikzpictures
+
%% The cached version
-\DeclareDocumentEnvironment{tikzpictureC}{O{}O{}b}{%
- \begin{CacheMe}{tikz,#2}[#1]%
- #3%
- \end{CacheMe}%
-}{}%
+\DeclareDocumentEnvironment{tikzpictureC}{D<>{}O{}O{}}{%
+ \begin{CacheMe}{tikzpicture,#1}[#2]%
+}{\end{CacheMe}}%
+
+%%%%%%
+%%%%%% The generic functions
+%%%%%%
+
+%% Usage: \robExtCacheEnvironment{myenv}
+\NewDocumentCommand{\robExtCacheEnvironment}{O{<>}mm}{%
+ %% We need to save the original environment to avoid infinite recursion if we disable externalization
+ %% https://tex.stackexchange.com/questions/695391/why-isnt-my-environment-restored/695398
+ \NewEnvironmentCopy{robExtEnvironmentOrig#2}{#2}%
+ \robExtAddToEnvironmentResetList{#2}%
+ \DeclareDocumentEnvironment{#2}{D#1{}}{%
+ \def\robExtEnvironmentOrigName{#2}%
+ \CacheMe{%
+ #3,%
+ set placeholder no import={__ROBEXT_MAIN_CONTENT__}{\begin{#2}__ROBEXT_MAIN_CONTENT_ORIG__\end{#2}},
+ ##1%
+ }%
+ }{\endCacheMe}%
+}
+\let\cacheEnvironment\robExtCacheEnvironment
+
+% \robExtShowPlaceholder{__ROBEXT_MAIN_CONTENT__}
+% \robExtShowPlaceholdersContents
+%%%% Borrowed and adapted from https://github.com/sasozivanovic/memoize/blob/master/xparse-arglist.sty
+%%%% see also https://tex.stackexchange.com/questions/695662/automatically-wrap-a-macro/695734
+%% The idea of the library is that it builds a string like
+%% [#2]<#3>{#4}
+%% in order to generate something like
+%% \NewDocumentCommand{\myfunction}{D<>{}O{coucou}D<>{yes}m}
+%% {
+%% \cacheMe[#1]{\myfunction[#2]<#3>{#4}}
+%% }
+%%%% _________________________________________________________________
+
+\def\robExtArgumentList{%
+ \expandafter\robExt@arglist\expandafter0\ArgumentSpecification.%
+}
+
+\def\robExt@arglist#1#2{%
+ \ifcsname robExt@arglist@#2\endcsname
+ \csname robExt@arglist@#2\expandafter\expandafter\expandafter\endcsname
+ \else
+ \expandafter\robExt@arglist@error
+ \fi
+ \expandafter{\the\numexpr#1+1\relax}%
+}
+
+% \robExt@arglist@...: #1 = the argument number
+\def\robExt@arglist@m#1{\noexpand\unexpanded{{#####1}}\robExt@arglist{#1}}
+\def\robExt@arglist@r#1#2#3{\noexpand\unexpanded{#2#####1#3}\robExt@arglist{#1}}
+\def\robExt@arglist@R#1#2#3#4{\noexpand\unexpanded{#2#####1#3}\robExt@arglist{#1}}
+\def\robExt@arglist@v#1{{Handled commands with verbatim arguments are not
+ supported}\robExt@arglist{#1}} % error
+\def\robExt@arglist@b#1{{This is not the way to handle
+ environment}\robExt@arglist{#1}} % error
+\def\robExt@arglist@o#1{\noexpand\unexpanded{[#####1]}\robExt@arglist{#1}}
+\def\robExt@arglist@d#1#2#3{\noexpand\unexpanded{#2#####1#3}\robExt@arglist{#1}}
+\def\robExt@arglist@O#1#2{\noexpand\unexpanded{[#####1]}\robExt@arglist{#1}}
+% \def\robExt@arglist@O#1#2{\noexpand\unexpanded{[#####1]}\robExt@arglist{#1}}
+\def\robExt@arglist@D#1#2#3#4{\noexpand\unexpanded{#2#####1#3}\robExt@arglist{#1}}
+\def\robExt@arglist@s#1{\noexpand\IfBooleanT{#####1}{*}\robExt@arglist{#1}}
+\def\robExt@arglist@t#1#2{\noexpand\IfBooleanT{#####1}{#2}\robExt@arglist{#1}}
+\csdef{robExt@arglist@+}#1{\expandafter\robExt@arglist\expandafter{\the\numexpr#1-1\relax}}%
+\csdef{robExt@arglist@.}#1{}
+% e,E: Embellishments are not supported.
+% > Argument processors are not supported. And how could they be?
+\def\robExt@arglist@error#1.{{Unknown argument type}}
+%%%% _________________________________________________________________
+
+%% Since the very first occurrence of D is not forwarded to the function
+%% we discard it:
+%% The first argument of \robExt@arglist@D is the number of the argument
+%% so #2#####1#3 reads as #2 = <, #### = #, #1 = > #3 = default value that can be discarded since it is already part of the argument spec.
+
+\def\robExt@arglist@D#1#2#3#4{%
+ \noexpand\unexpanded{%
+ \ifnum #1=1 % If it is the first argument D, then we do not add anything to the argument string
+ \else #2#####1#3\fi}\robExt@arglist{#1}%
+}
+
+%% Usage: \robExtCacheCommand[delimiters]{name command}[argument specification]{style}
+%% Inspired and modified from
+%% https://github.com/sasozivanovic/memoize/blob/81d960aa547148bdb38fea89917eda1476c9bace/memoize.sty#L744
+\NewDocumentCommand{\robExtCacheCommand}{O{<>}mom}{%
+ %% We get the specification of the command, like "O{}mm"
+ \IfNoValueTF{#3}{%
+ \expandafter\GetDocumentCommandArgSpec\csname #2\endcsname%
+ }{%
+ \def\ArgumentSpecification{#3}%
+ }%
+ \edef\ArgumentSpecification{D#1{}\ArgumentSpecification}%
+ \robExtAddToCommandResetList{#2}%
+ % We copy the original definition for later (if externalization is disabled)
+ \expandafter\DeclareCommandCopy\csname robExtCommandOrig#2\expandafter\endcsname\csname #2\endcsname%
+ \edef\robExt@marshal{%
+ \noexpand\DeclareDocumentCommand%
+ \expandonce{\csname #2\endcsname}%
+ {\expandonce{\ArgumentSpecification}}%
+ {%
+ \noexpand\def\noexpand\robExtCommandOrigName{#2}%
+ % todo: add a hook for users setup; prevent user from changing \MemoizeWrapper?
+ \edef\noexpand\robExt@marshal{%
+ \noexpand\noexpand\noexpand\robExtRescanHashRobust{\noexpand\noexpand\noexpand\robExtCacheMe[\detokenize{#4}, \noexpand\detokenize{####1}]{%
+ \noexpand\noexpand\expandonce{\csname #2\endcsname}%
+ \robExtArgumentList%
+ }%
+ }%
+ }%
+ % For debug
+ %\noexpand\show\noexpand\robExt@marshal%
+ \noexpand\robExt@marshal%
+ }%
+ }%
+ % for debug
+ %\show\robExt@marshal%
+ \robExt@marshal%
+}
+\let\cacheCommand\robExtCacheCommand
diff --git a/macros/latex/contrib/robust-externalize/robust-externalize.tex b/macros/latex/contrib/robust-externalize/robust-externalize.tex
index 561cde37a5..0a8f57bef9 100644
--- a/macros/latex/contrib/robust-externalize/robust-externalize.tex
+++ b/macros/latex/contrib/robust-externalize/robust-externalize.tex
@@ -16,10 +16,17 @@
\makeatletter
\usepackage{robust-externalize}
\makeatother
-
+\robExtConfigure{
+ enable optimizations
+}
+\usepackage{zx-calculus}
+\usepackage{forest}
+\setlength{\marginparwidth}{2cm}
+\usepackage{todonotes}
% Loads the great package that produces tikz-like manual (see also tikzcd for examples)
\input{pgfmanual-en-macros.tex} % Is supposed to be included in recent TeX distributions, but I get errors...
+
%% For verbatim environments:
\NewDocumentEnvironment{codeAndResult}{}{\XSIMfilewritestart{\jobname-codeAndResult-tmp-file-you-can-remove.tmp}}%
@@ -87,23 +94,35 @@
{\Large\bfseries Cache anything (\tikzname, python…),\\in a robust, efficient and pure way.}
\vspace{1em}
- {Léo Colisson \quad Version 1.0}\\[3mm]
+ {Léo Colisson \quad Version 2.0}\\[3mm]
{\href{https://github.com/leo-colisson/robust-externalize}{\texttt{github.com/leo-colisson/robust-externalize}}}
\end{center}
-
\tableofcontents
\bigskip
-\textbf{WARNING: This library is young and has not been tested extensively (and is an important rewrite of a previous version). Even if we try to stay backward compatible, the only guaranteed way to be immune to changes is to copy/paste the library in your main project folder. Please report any bug to \url{https://github.com/leo-colisson/robust-externalize}, or let us know if it works!}
+\textbf{WARNING: This library is young and might lack some testing (and is an important rewrite of a previous version), but v2.0 is definitely usable. Even if we try to stay backward compatible, the only guaranteed way to be immune to changes is to copy/paste the library in your main project folder. Please report any bug to \url{https://github.com/leo-colisson/robust-externalize}!}
+
+\textbf{WARNING 2: the coming version 2.0 improves significantly the compilation time compared with 1.0 that was surprisingly slow. Now, it is fairly well optimized (but the code needs a bit of cleaning and documentation before doing an official release)}
+
\section{A taste of this library}
-This library allows you to cache any language: not only \LaTeX{} documents and \tikzname{} images, taking into account depth and overlays:
+This library allows you to cache any language: not only \LaTeX{} documents and \tikzname{} images, taking into account depth and overlays, but also arbitrary code. To use it, make sure to have v2.0 installed (see instructions below), and load:
+\begin{verbatim}
+\usepackage{robust-externalize}
+\robExtConfigure{
+ % To display instructions in the PDF to manually compile pictures if
+ % you forgot/do not want to compile with -shell-escape
+ enable fallback to manual mode,
+}
+\end{verbatim}
+Then type something like this (note the |C| for |cached| at the end of |tikzpictureC|, see below to override the original command), and compile with |pdflatex -shell-escape yourfile.tex| (or \textcolor{red}{\textbf{read below if you do not want to use }}|-shell-escape|):
\begin{codeexample}[width=0pt,vbox]
\robExtConfigure{
- tikz/.append style={
+ add to preset={tikz}{
+ % we load some packages that will be loaded by figures based on the tikz preset
add to preamble={\usepackage{pifont}}
}
}
@@ -114,8 +133,7 @@ This library allows you to cache any language: not only \LaTeX{} documents and \
\end{tikzpictureC} and you can see that overlay and depth works.
\end{codeexample}
-
-\noindent but also arbitrary code (e.g.\ python). You can also define arbitrary compilation commands, inclusion commands, and presets to fit you need. For instance, you can create a preset to obtain:
+You can also cache arbitrary code (e.g.\ python). You can also define arbitrary compilation commands, inclusion commands, and presets to fit you need. For instance, you can create a preset to obtain:
\begin{codeAndResult}
\begin{CacheMeCode}{python print code and result, set title={The for loop}}
@@ -124,13 +142,163 @@ for name in ["Alice", "Bob"]:
\end{CacheMeCode}
\end{codeAndResult}
-Actually, we also provide this style by default (and explain how to write it yourself), you just make sure to load:
+Actually, we also provide this style by default (and explain how to write it yourself), just make sure to load:
\begin{verbatim}
\usepackage{pythonhighlight}
\usepackage{tcolorbox}
\end{verbatim}
-To achieve a pleasant and configurable interface, we introduced placeholders, that can be of independent interest.
+You can also cache any environment and command using something like:
+\begin{itemize}
+\item For environments:
+\begin{codeAndResult}
+% We cache the environment forest
+\cacheEnvironment{forest}{latex, add to preamble={\usepackage{forest}}}
+
+A forest tree automatically cached %
+\begin{forest}
+ [VP
+ [DP[John]]
+ [V’
+ [V[sent]]
+ [DP[Mary]]
+ [DP[D[a]][NP[letter]]]
+ ]
+ ]
+\end{forest}\\
+And one not cached: %
+\begin{forest}<disable externalization>
+ [VP
+ [DP[John]]
+ [V’
+ [V[sent]]
+ [DP[Mary]]
+ [DP[D[a]][NP[letter]]]
+ ]
+ ]
+\end{forest}
+\end{codeAndResult}
+\item For commands:
+\begin{codeAndResult}
+% We cache the command \zx
+% O{} = optional argument, m = mandatory argument.
+% Autodetected if command defined with xparse (NewDocumentCommand)
+% (in this example it is redundant since zx IS defined with xparse syntax)
+\cacheCommand{zx}[O{}O{}O{}m]{latex, add to preamble={\usepackage{zx-calculus}}}
+
+A ZX figure %
+\zx{
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ*{a\pi} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+}, we can disable externalization: %
+\zx<disable externalization>{
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ*{a\pi} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+} or add more options: %
+\zx<add to preamble={\usepackage{amsmath}\def\hello#1{Hello #1.}}>{
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ{\text{\hello{Alice}}} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+}
+\end{codeAndResult}
+\end{itemize}
+You can also cache all tikz pictures by default, except those that are run from some commands (as remember picture does not work yet, this is important). For instance, this code will allow you to freely use the |todonotes| package (that uses internally tikz but is not cachable with this library since it uses remember picture) while caching all other elements:
+\begin{codeexample}[code only]
+ %% this will cache \tikz and tikzpictures by default (using the tikz preset)
+ \cacheTikz
+ %% possibly add stuff to the tikz preset
+ \robExtConfigure{
+ add to preset={tikz}{
+ add to preamble={
+ \def\whereIAm{(I am cached)}
+ }
+ },
+ }%
+ %% We say not to cache the todo commands:
+ \cacheCommand{todo}[O{}m]{disable externalization}%
+ \todo{Check how to use cacheCommand and cacheEnvironment}
+ \tikz[baseline=(A.base)] \node(A)[rounded corners,fill=green]{my cached node \whereIAm};
+\end{codeexample}
+
+will gives you: {%
+ %% this will cache \tikz and tikzpictures by default (using the tikz preset)
+ \cacheTikz
+ %% possibly add stuff to the tikz preset
+ \robExtConfigure{
+ add to preset={tikz}{
+ add to preamble={
+ \def\whereIAm{(I am cached)}
+ }
+ },
+ }%
+ %% We say not to cache the todo commands:
+ \cacheCommand{todo}[O{}m]{disable externalization}%
+ \todo{Check how to use cacheCommand and cacheEnvironment}
+ \tikz[baseline=(A.base)] \node(A)[rounded corners,fill=green]{my cached node \whereIAm};
+}
+
+Note that most options can either be specified anywhere in the document like
+\begin{verbatim}
+\robExtConfigure{
+ disable externalization
+}
+\end{verbatim}
+, inside a preset (that is nothing more than a pgf style), or in the options of the cached environment (either inside |CacheMe| or inside the first parameter |<...>| for automatically cached environments):
+\begin{codeexample}[vbox]
+ \robExtConfigure{
+ new preset={my preset with xcolor}{
+ latex, % load the latex preset, you can also use the tikz preset and more
+ add to preamble={
+ % load xcolor in the preamble of the cached document
+ \usepackage{xcolor}
+ },
+ },
+ }
+ \begin{CacheMe}{my preset with xcolor, add to preamble={\def\hello#1{Hello #1!}} }
+ \begin{minipage}{5cm}
+ \textcolor{red}{\hello{Alice} See, you can cache any data, including minipages,
+ define macros, combine presets, override a single picture or a whole part of
+ a document etc.}
+ \end{minipage}
+ \end{CacheMe}
+\end{codeexample}
+(see that |CacheMe| can be used to cache arbitrary pictures)
+
+Or include images generated in python:
+
+\begin{codeexample}[code only]
+\begin{CacheMeCode}{python, set includegraphics options={width=.8\linewidth}}
+import matplotlib.pyplot as plt
+year = [2014, 2015, 2016, 2017, 2018, 2019]
+tutorial_count = [39, 117, 111, 110, 67, 29]
+plt.plot(year, tutorial_count, color="#6c3376", linewidth=3)
+plt.xlabel('Year')
+plt.ylabel('Number of futurestud.io Tutorials')
+plt.savefig("__ROBEXT_OUTPUT_PDF__")
+\end{CacheMeCode}
+\end{codeexample}
+
+You can also include files from the root folder, if you want, recompile all pictures if this files changes (nice to ensure maximum purity):
+\begin{codeexample}[width=0pt,vbox]
+\begin{CacheMe}{latex,
+ add dependencies={common_inputs.tex},
+ add to preamble={\input{__ROBEXT_WAY_BACK__common_inputs.tex}}}
+ The answer is \myValueDefinedInCommonInputs.
+\end{CacheMe}
+\end{codeexample}
+
+
+We also provide many other things, among others:
+\begin{itemize}
+\item To achieve a pleasant and configurable interface (e.g. pass options to a preset with default values), we introduced placeholders, that can be of independent interest.
+\item A way to compile a template via:\\
+ |new compiled preset={compiled ZX}{templateZX, compile latex template}{}|\\
+ in order to make the compilation even faster (but you cannot use presets except |add to preamble|)
+\item A highly configurable template, compilation and inclusion system, to cache basically anything
+\item A way to compile all images in parallel during the first run, so that the first run becomes faster to compile than a normal run
+\item Commands to automatically clean the cache while keeping pictures in use
+\item And more\dots
+\end{itemize}
+
\section{Introduction}
@@ -145,7 +313,7 @@ Similarly, you might want to cache the result of some codes, for instance a text
\tikzname{} has an externalize library to pre-compile these images on the first run. Even if this library is quite simple to use, it has multiple issues:
\begin{itemize}
\item If you add a picture before existing pre-compiled pictures, the pictures that are placed after will be recompiled from scratch. This can be mitigated by manually adding a different prefix to each picture, but it is highly not practical to use.
-\item To compile each picture, TikZ's externalize library reads the document's preamble and needs to process (quickly) the whole document. In large documents (or in documents relying on many packages), this can result in a significant loading time, sometimes much bigger than the time to compile the document without the externalize library: for instance, if the document takes 10 seconds to be processed, and if you have 200 pictures that take 1s each to be compiled, the first compilation with the TikZ's externalize library will take roughly half an hour instead of 3mn without the library. And if you add a single picture at the beginning of the document… you need to restart everything from scratch. For these reasons, I was not even able to compile my thesis with TikZ's external library in a reasonable time.
+\item To compile each picture, TikZ's externalize library reads the document's preamble and needs to process (quickly) the whole document. In large documents (or in documents relying on many packages), this can result in a significant loading time, sometimes much bigger than the time to compile the document without the externalize library: for instance, if the document takes 10 seconds to be processed, and if you have 200 pictures that take 1s each to be compiled, the first compilation with the TikZ's externalize library will take roughly half an hour (200 $\times$ 10s = 33mn) instead of 3mn without the library. And if you add a single picture at the beginning of the document… you need to restart everything from scratch. For these reasons, I was not even able to compile my thesis with TikZ's external library in a reasonable time.
\item If two pictures share the same code, it will be compiled twice
\item Little purity is enforced: if a macro changes before a pre-compiled picture that uses this macro, the figure will not be updated. This can result in different documents depending on whether the cache is cleared or not.
\item As far as I know, it is made for TikZ picture mostly, and is not really made for inserting other stuff, like matplotlib images generated from python etc...
@@ -156,23 +324,31 @@ Similarly, you might want to cache the result of some codes, for instance a text
\paragraph{What is supported?}
-You can cache most things, including tikz pictures, (including ones with overlays (but not with remember picture), with depth etc.), python code etc. We tried to make the library as customizable as possible to be useful in most scenarios. You can also feed data back to the main document (say that you want to compute a value that takes time to compute, or compute the number of pages of the produced document in order to increase the number of pages accordingly\dots{}).
+You can cache most things, including tikz pictures, (including ones with overlays (but not with remember picture), with depth etc.), python code etc. We tried to make the library as customizable as possible to be useful in most scenarios. You can also send some data (e.g.\ : the current page) to the compiled pictures, and feed some data back to the main document (say that you want to compute a value that takes time to compute, or compute the number of pages of the produced document in order to increase the number of pages accordingly\dots{}). Since v2.0, you can also cache automatically any environment.
\paragraph{What is not supported?}
-We do not yet support remember picture, and you can't use (yet) cross-references inside your images (at least not without further hacks). Note that this library is quite young, so expect untested things.
+We do not yet support remember picture, and you can't use (yet) cross-references inside your images (at least not without further hacks) or links as links are stripped when the pdf is included. I might have some ideas to solve this\footnote{\url{https://tex.stackexchange.com/questions/695277/clickable-includegraphics-for-cross-reference-data}}, meanwhile you can just disable locally the library on problematic figures. Note that this library is quite young, so expect untested things.
\paragraph{What OS are supported?}
-I tested the library mostly on Linux systems, but the library should work on all OS. Please let me know if it fails for you.
+I tested the library on Linux and Windows, but the library should work on all OS, including MacOs. Please let me know if it fails for you.
\paragraph{Do I need to compile using -shell-escape?}
Since we need to compile the images via an external command, the simpler option is to add the argument |-shell-escape| to let the library run the compilation command automatically (this is also the case of \tikzname's externalize library). However, people worried by security issues of |-shell-escape| (that allows arbitrary code execution if you don't trust the \LaTeX{} code) might be interested by these facts:
\begin{itemize}
-\item If images are all already cached, you don't need to enable \texttt{-shell-escape} (this might be interesting e.g. to send the files a pre-cached document to the arxiv or to a publisher: just make sure to include the cache folder).
-\item You can choose to display a dummy content until you choose to compile them.
-\item You can compile manually the images: all the commands that are left to be executed are listed in \texttt{robExt-compile-missing-figures.sh} and you can just run them, either with \texttt{bash robExt-compile-missing-figures.sh} or by typing them manually (most of the time it's only a matter of running \texttt{pdflatex somefile.tex}).
+\item You can choose to display a dummy content explaining how to manually compile the pictures until they are compiled, see |enable fallback to manual mode|.
+\item You can compile manually the images: all the commands that are left to be executed are also listed in \texttt{robExt-compile-missing-figures.sh} and you can just inspect and run them, either with \texttt{bash robExt-compile-missing-figures.sh} or by typing them manually (most of the time it's only a matter of running \texttt{pdflatex somefile.tex}).
+\item If you allowed:
+ \begin{itemize}
+ \item |pdflatex| (needed to compile latex documents)
+ \item |cd| (not needed when using |no cache folder|)
+ \item and |mkdir| (not needed when using |no cache folder| or if the cache folder that defaults to |robustExternalize| is already created)
+ \end{itemize}
+ to run in restricted mode (so without enabling |-shell-escape|), then there is no need for |-shell-escape|. In that case, set |force compilation| and this library will compile even if |-shell-escape| is disabled.
+\item If images are all already cached, you don't need to enable \texttt{-shell-escape} (this might be interesting e.g. to send a pre-cached document to the arxiv or to a publisher: just make sure to include the cache folder).
+\item We use very few commands to compile latex files, basically only pdflatex, mkdir (to create the cache folder if needed) and cd (if the cache folder is not present). You might want to allow them in restricted mode.
\end{itemize}
@@ -182,17 +358,37 @@ Yes: overleaf automatically compiles documents with |-shell-escape|, so nothing
\paragraph{Do you have some benchmarks?}
-On an early draft of a small paper containing 76 small tikz-cd based pictures (from my other zx-calculus library), we measured:
+We completely rewrote the \href{https://github.com/leo-colisson/robust-externalize/commit/09a05a86ec9c04eb6687b75831ebb84185786ac5}{original library} to introduce the notion of placeholders (before, the template was fixed forever), allowing for greater flexibility. The original rewrite (1.0) had really poor performance compared to the original library (only x3 improvement compared to no externalization, while the old library could be 20x faster), but we made some changes (v2.0) that correct this issue. Here is a benchmark we made on an article with 159 small pictures (ZX diagrams from the zx-calculus library):
+\begin{itemize}
+\item without externalization: 1mn25
+\item with externalization, v2.0 (first run, not in parallel): 3mn05, so takes twice the time; but (first run in parallel) takes 60s (so faster by a factor of 1.5).
+\item with externalization, v2.0 (next runs): 5.77s (it is 15x times faster)
+\item with externalization, v2.0, with a ``compiled'' template (less flexible) like in the old version: 4.0s (22x faster)
+\item with externalization, old library (next runs): 4.16s (so 21x faster)
+\end{itemize}
+
+\paragraph{Can I compile pictures in parallel to speed up the first run?} If you are worried by the time taken for the first run, you can also run it in manual mode and use for instance GNU |parallel| (or any tool of you choice) to run all commands in the file |\jobname-robExt-compile-missing-figures.sh| in parallel. To do that:
\begin{itemize}
-\item 35 seconds for a normal compilation without externalization
-\item 75 seconds for the first compilation with this library
-\item 2.4 seconds for the next runs
+\item First add |\robExtConfigure{enable manual mode}| in your file
+\item Create the cache folder, e.g.\ using |mkdir robustExternalize|
+\item Compile your file, with, e.g.\ |pdflatex yourfile.tex| (in my benchmark: 4.2s)
+\item This should create a file |yourfile-robExt-compile-missing-figures.sh|, with each line containing a compilation command like this (the command should be compatible with Windows, Mac and Linux, if not, let me know on github):
+\begin{verbatim}
+cd robustExternalize/ && pdflatex -halt-on-error "robExt-4A806941E86C6B657A0CB3D160CFFF3E.tex
+\end{verbatim}
+ \textbf{IMPORTANT}: \LaTeX{} might render \textbf{multiple times} the same picture if it is inside some particular environments (align, tables\dots), so this file can contain duplicates if you inserted cached data inside. To avoid running the same command twice, \textbf{be sure to remove duplicates!} On Linux, this can be done by piping the file into |sort| and |uniq| (if your files can depend on previously compiled elements as explained in \cref{sec:passOutputToOtherTemplate}, you should additionally preserve \mylink{https://unix.stackexchange.com/questions/194780/remove-duplicate-lines-while-keeping-the-order-of-the-lines}{the order of the lines}). Since this is anyway a rather advanced use case, we will not consider that case for simplicity.
+\item Run all these command in parallel, for instance on Linux you can install |parallel|, and run the following command (|--bar| displays a progress bar):
+\begin{verbatim}
+cat yourfile-robExt-compile-missing-figures.sh | sort | uniq | parallel --bar --jobs '200%'
+\end{verbatim}
+(in my benchmark, it ran during 52s, so 1.6x faster than the original compilation)
+\item Recompile the original document with |pdflatex yourfile.tex|
\end{itemize}
-So during the first compilation, we lost a x2 factor (roughly an additional time of .5 seconds per picture coming from the time to start \LaTeX{}, it seems like on average a picture takes .5 seconds to be built in my benchmark), but then we have a speedup of x15 (2.43s instead of 34.63s) for all subsequent runs. And I expect this to be even higher with more pictures and more complex documents.
+In my benchmark, the total time is 2x4.2s + 52s = 60s, so 1.5 times faster than a normal command (of course, this depends a lot on the preamble of the file that you compile, since the loading time of the file is the main bottleneck for the first compilation; the advantage here is that it is easy to include only the necessary things in the preamble of cached pictures, possibly creating different presets if it is easier to manage it this way).
\paragraph{Can I use version-control to keep the cached files in my repository?} Sure, each cached figure is stored in a few files (typically one pdf and one \LaTeX{} file, plus the source) having the same prefix (the hash), avoiding collision between runs. Just commit these files and you are good to go.
-\paragraph{Can you deal with baseline position ?} Yes, the depth of the box is automatically computed and used to include the figure by default.
+\paragraph{Can I deal with baseline position and overlays ?} Yes, the depth of the box is automatically computed and used to include the figure by default, and additional margin is added to the image (30cm by default) to allow overlay text.
\paragraph{How is purity enforced?} Purity is the property that if you remove the cached files and recompile your document, you should end-up with the same output. To enforce purity, we compute the hash of the final program, including the compilation command and the dependency files used for instance in |\input{include.tex}| (unless you prefer not to, for instance to keep parts of the process impure for efficiency reasons), and put the code in a file named based on this hash. Then we compile it if it has not been used before, and include the output. Changing a single character in the file, the tracked dependencies, or the compilation command will lead to a new hash, and therefore to a new generated picture.
@@ -200,51 +396,82 @@ So during the first compilation, we lost a x2 factor (roughly an additional time
\paragraph{Can I extend it easily?} We tried to take a quite modular approach in order to allow easy extensions. Internally, to support a new cache scheme, we only expect a string containing the program (possibly produced using a template), a list of dependencies, a command to compile this program (e.g. producing a pdf and possibly a tex file with the properties (depth…) of the pdf), and a command to load the result of the compilation into the final document (called after loading the previously mentioned optional tex file). Thanks to pgfkeys, it is then possible to create simple pre-made settings to automatically apply when needed.
-\paragraph{How does it compare with \url{https://github.com/sasozivanovic/memoize}?} I recently became aware of the great \url{https://github.com/sasozivanovic/memoize}. While me aim to solve a similar goal, our approaches are quite different. While we focus on purity, and therefore create a different file for each picture, the above project puts all pictures in a single file and compile them all at once to avoid losing time to run the latex command for each picture (this mostly makes a difference for the first compilation). Our understanding of the main differences is the following:
+\paragraph{How does it compare with \url{https://github.com/sasozivanovic/memoize}?} I recently became aware of the great \url{https://github.com/sasozivanovic/memoize}. While we aim to solve a similar goal, our approaches are quite different. While I focus on purity, and therefore create a different file for each picture, the above project puts all pictures in a single file and compile them all at once to avoid losing time to run the latex command for each picture (this mostly makes a difference for the first compilation). Our understanding of the main differences is the following:
Pros of \url{https://github.com/sasozivanovic/memoize}:
\begin{itemize}
-\item The above library is likely to be quicker on the first run since it packs everything in a single file (so you save the time to run latex for each picture). On the other hand, we can load in the preamble exactly what is needed for the picture (we do not load all the preamble of the main file), so our startup time is not huge (it adds .5s per picture in my tests when using the |zx-calculus| library), and you can still commit the cached file to help with recompiling the document elsewhere.
-\item It seems to be easier to setup as they do not need to specify the preamble of the file to compile (the preamble of the main file is used), and tikz picture are automatically memoized (we provide |\robExtExternalizeAllTikzpictures| for that, but you still need to specify the preamble once).
+\item The above library is likely to be quicker on the first run since it packs everything in a single file (so you save the time to run latex for each picture). On the other hand, we can load in the preamble exactly what is needed for the picture (we do not load all the preamble of the main file), so our startup time is not huge (it adds 1s per picture in my tests when using the |zx-calculus| library), and you can still either run it in parallel to save time (as far as I know this is not possible with |memoize|), or commit the cached file to help with recompiling the document elsewhere.
+\item It seems to be easier to setup as they do not need to specify the preamble of the file to compile (the preamble of the main file is used), and tikz pictures are automatically memoized (we provide |\cacheTikz| for that, but you still need to specify the preamble once).
+\item Even if it does not officially support contexts, context might be automatically transmitted (while we need to explicitly pass the context). However, this can break purity (see below).
\end{itemize}
Cons of \url{https://github.com/sasozivanovic/memoize}:
\begin{itemize}
-\item The purity is not enforced so strongly since all images are in the same file. Notably, the hash only depends on the picture, but not on its context. So for instance if you define |\def\mycolor{blue}| before the picture, and use |\mycolor| inside the picture, if you change later the color to, say, |\def\mycolor{red}|, the picture will not be recompiled (so cleaning the cache and recompiling would produce a different result). In our case, the purity is always strictly enforced (unless you choose not to).
+\item The purity is not enforced so strongly since all images are in the same file. Notably, the hash only depends on the picture, but not on its context. So for instance if you define |\def\mycolor{blue}| before the picture, and use |\mycolor| inside the picture, if you change later the color to, say, |\def\mycolor{red}|, the picture will not be recompiled (so cleaning the cache and recompiling would produce a different result). In our case, the purity is always strictly enforced (unless you choose not to) since the context must be explicitly passed to the compiled file.
\item As a result, the above library has poor support for contexts (in our case, you can easily, for instance, make a picture depend on the current page, and recompile the picture only if the current page changes: you can also do it the other way, and change some counters, say, depending on the cached file).
\item The above library only focuses on \LaTeX{} while our library works for any language
-\item The above library can only produce pdf formats, while we can generate any format (text, tex, jpg\dots{} and even videos that I include in my beamer presentation).
+\item The above library can only produce pdf formats, while we can generate any format (text, tex, jpg\dots{} and even videos that I include in my beamer presentations\dots{} but it is another question).
\item We have an arguably more complete documentation.
\end{itemize}
Note that |remember picture| is not working in both libraries.
-\section{Quickstart}
+\section{Tutorial}
\subsection{Installation}
To install the library, just copy the |robust-externalize.sty| file into the root of the project. Then, load the library using:\\
-|\usepackage{robust-externalize}|
+\begin{verbatim}
+\usepackage{robust-externalize}
+\end{verbatim}
+
+If you want to display a message in the pdf on how to manually compile the file if |-shell-escape| is disabled, you can also load this configuration (only available on v2.0):
+
+\begin{verbatim}
+\robExtConfigure{
+ enable fallback to manual mode,
+}
+\end{verbatim}
+
+\noindent (otherwise, it will give you an error if |-shell-escape| is disabled and if some pictures are not yet cached)
+
+If you forget/do not want to enable |-shell-escape|, this will give you this kind of message:
+
+\noindent {
+ \robExtConfigure{
+ enable manual mode
+ }
+ \begin{tikzpictureC}[baseline=(A.base)]
+ \node[fill=red, rounded corners](A){I must be manually compiled.};
+ \node[fill=red, rounded corners, opacity=.3,overlay] at (A.north east){I am an overlay text};
+ \end{tikzpictureC}
+}
\subsection{Caching a tikz picture}
If you only care about \tikzname's picture, you have 3 options:
\begin{enumerate}
-\item Call once |\robExtExternalizeAllTikzpictures| that will redefine |tikzpicture| to use our library (if you use this solution, make sure to read how to disable externalization (\cref{sec:disableExternalization}) as we do not support for instance |remember picture|). Then, configure the default preamble for cached files as explained below.
+\item Call once |\cacheTikz| that will redefine |tikzpicture| and |\tikz| to use our library (if you use this solution, make sure to read how to disable externalization (\cref{sec:disableExternalization}) as we do not support for instance |remember picture|). Then, configure the default preamble for cached files as explained below by extending the |tikz| or |tikzpicture| presets (that first loads |tikz|).
+\item Use the generic commands that allows you to wrap an arbitrary environment or command:
+\begin{verbatim}
+% name environment ---v v----- preset options
+\robExtCacheEnvironment{tikzpicture}{tikzpicture}
+\end{verbatim}
+ Note that we do recommend to use |\robExtCacheCommand| for the macro version |\tikz| since |\tikz| has a quite complicated parsing strategy. |\cacheTikz| takes care of this already.
\item Use |tikzpictureC| instead of |tikzpicture| (this is mostly done to easily convert existing code to this library, but works only for |tikz| pictures).
\item Use the more general |CacheMe| environment, that can cache \tikzname, \LaTeX{}, python, and much more.
\end{enumerate}
-These 3 options are illustrated below (note that the newly defined |tikzpicture| and |tikzpictureC| accept a second optional argument that contains the options to pass to |CacheMe| after loading the |tikz| preset):
+These 3 options are illustrated below (note that the newly defined |tikzpicture| and |tikzpictureC| accept a second optional argument that contains the options to pass to |CacheMe| after loading the |tikzpicture| preset, that loads itself the |tikz| preset first):
Option 1:
\begin{codeexample}[width=0pt]
%% We override the default tikzpicture environment
%% to externalize all pictures
%% Warning: it will cause troubles with pictures relying on |remember pictures|
-\robExtExternalizeAllTikzpictures
+\cacheTikz
I am a cached picture: \begin{tikzpicture}[baseline=(A.base)]
\node[draw,rounded corners,fill=pink!60](A){Hello World!};
@@ -253,63 +480,102 @@ I am a cached picture: \begin{tikzpicture}[baseline=(A.base)]
Option 2:
\begin{codeexample}[width=0pt]
+\cacheEnvironment{tikzpicture}{tikzpicture}
+I am a cached picture: \begin{tikzpicture}[baseline=(A.base)]
+ \node[draw,rounded corners,fill=pink!60](A){Hello World!};
+\end{tikzpicture}.
+\end{codeexample}
+
+Option 3:
+\begin{codeexample}[width=0pt]
I am a cached picture: \begin{tikzpictureC}[baseline=(A.base)]
\node[draw,rounded corners,fill=pink!60](A){Hello World!};
\end{tikzpictureC}.
\end{codeexample}
-Option 3:
+Option 4:
\begin{codeexample}[width=0pt]
-I am a cached picture: \begin{CacheMe}{tikz}[baseline=(A.base)]
+I am a cached picture: \begin{CacheMe}{tikzpicture}[baseline=(A.base)]
\node[draw,rounded corners,fill=pink!60](A){Hello World!};
\end{CacheMe}.
\end{codeexample}
-Since |CacheMe| is more general as it applies also to non-tikz pictures (just replace |tikz| with the style of your choice), we will mostly use this syntax from now.
+Since |CacheMe| is more general as it applies also to non-tikz pictures (just replace |tikzpicture| with the style of your choice), we will mostly use this syntax from now.
\subsection{Custom preamble}
-Note that the pictures are compiled in a separate document, with a different preamble and class (we use the standalone class). This is interesting to reduce the compilation time of each picture (loading a large preamble is really time consuming) and to avoid unnecessary recompilation (do you want to recompile all your pictures when you add a single new macro?) without sacrificing the purity. But of course, you need to provide the preamble of the pictures. The easiest way is probably to modify the |tikz| preset (you can also modify the |latex| preset if you want the change to apply to all \LaTeX{} documents):
+Note that the pictures are compiled in a separate document, with a different preamble and class (we use the standalone class). This is interesting to reduce the compilation time of each picture (loading a large preamble is really time consuming) and to avoid unnecessary recompilation (do you want to recompile all your pictures when you add a single new macro?) without sacrificing the purity. But of course, you need to provide the preamble of the pictures. The easiest way is probably to modify the |tikz| preset (since |tikzpicture| loads this style first, it will also apply to tikzpictures. Note that you can also modify the |latex| preset if you want the change to apply to all \LaTeX{} documents):
\begin{codeexample}[width=0pt,vbox]
\robExtConfigure{
- tikz/.append style={
+ add to preset={tikz}{
add to preamble={\usetikzlibrary{shadows}},
},
}
See, tikz's style now packs the |shadows| library by default: %
- \begin{CacheMe}{tikz}[even odd rule]
+ \begin{CacheMe}{tikzpicture}[even odd rule]
\filldraw [drop shadow,fill=white] (0,0) circle (.5) (0.5,0) circle (.5);
\end{CacheMe}
\end{codeexample}
-You can also choose to overwrite it for a single picture (or even a block of picture if you run the |\robExtConfigure| and |CacheMe| inside a group |{ ... }|):
+and you can also create a new preset, and why not mix multiple presets together:
+\begin{codeexample}[width=0pt,vbox]
+ \robExtConfigure{
+ new preset={load forest}{
+ latex,
+ add to preamble={\usepackage{forest}},
+ },
+ new preset={load hello}{
+ add to preamble={\def\hello#1{Hello #1.}},
+ },
+ }
+
+ \begin{CacheMe}{load forest, load hello}
+ \begin{forest}
+ [VP
+ [DP[\hello{John}]]
+ [V’
+ [V[sent]]
+ [DP[Mary]]
+ [DP[D[a]][NP[letter]]]
+ ]
+ ]
+ \end{forest}
+ \end{CacheMe}
+\end{codeexample}
+
+
+\textbf{Note:} the |add to preset| and |new preset| directives have been added in v2.0, together with the |tikzpicture| preset. In v1.0, you would do |tikz/.append style={...}| (and you can still do this if you prefer), the difference is that |.append style| and |.style| require the user to double all hashes like |\def\mymacro##1{Hello ##1.}| which can lead to confusing errors.
+
+You can also choose to overwrite the preset options for a single picture (or even a block of picture if you run the |\robExtConfigure| and |CacheMe| inside a group |{ ... }|):
\begin{codeexample}[width=0pt,vbox]
See, you can add something to the preamble of a single picture: %
- \begin{CacheMe}{tikz, add to preamble={\usetikzlibrary{shadows}}}[even odd rule]
+ \begin{CacheMe}{tikzpicture, add to preamble={\usetikzlibrary{shadows}}}[even odd rule]
\filldraw [drop shadow,fill=white] (0,0) circle (.5) (0.5,0) circle (.5);
\end{CacheMe}
\end{codeexample}
-Note that if you use the |tikzpictureC| or |tikzpicture| syntax, you want to add the options after the tikz options (leave an empty bracket if there is none):
+Note that if you use the |tikzpictureC| or |tikzpicture| syntax, you want to add the options right after the name of the command or environment, enclosed in |<>| (by default):
\begin{codeexample}[width=0pt,vbox]
See, you can add something to the preamble of a single picture: %
- \begin{tikzpictureC}[even odd rule][add to preamble={\usetikzlibrary{shadows}}]
+ \begin{tikzpictureC}<add to preamble={\usetikzlibrary{shadows}}>[even odd rule]
\filldraw [drop shadow,fill=white] (0,0) circle (.5) (0.5,0) circle (.5);
\end{tikzpictureC}
\end{codeexample}
+\textbf{Important}: Note that the preset options can be specified in a number of places: in |\robExtConfigure| (possibly in a group, or inside a preset), in the options of the picture, in the default options of |cacheEnvironment| and |cacheCommand| etc. Most options can be used in all these places, the only difference being the scope of the options.
+
\subsection{Dependencies}\label{sec:dependencies}
It might be handy to have a file that is loaded in both the main document and in the cached pictures. For instance, if you have a file |common_inputs.tex| that you want to input in both the main file and in the cached files, that contains, say:\\
|\def\myValueDefinedInCommonInputs{42}|\\
-then you can add it as a dependency this way (here we use the |latex| preset that does not wrap the code inside a |tikzpicture| only to illustrate that we can also cache things that is not generated by tikz):
+then you can add it as a dependency this way (here we use the |latex| preset that does not wrap the code inside a |tikzpicture| only to illustrate that we can also cache things that are not generated by tikz):
\begin{codeexample}[width=0pt,vbox]
\begin{CacheMe}{latex,
add dependencies={common_inputs.tex},
- add to preamble={\input{__ROBEXT_WAY_BACK__/common_inputs.tex}}}
+ add to preamble={\input{__ROBEXT_WAY_BACK__common_inputs.tex}}}
The answer is \myValueDefinedInCommonInputs.
\end{CacheMe}
\end{codeexample}
@@ -317,17 +583,42 @@ Note that the placeholder |__ROBEXT_WAY_BACK__| contains the path from the cache
You can note that we used |add dependencies={common_inputs.tex}|: this allows us to recompile the files if |common_inputs.tex| changes. If you do not want this behavior (e.g. |common_inputs.tex| changes too often and you do not want to recompile everything at every change), you can remove this line, but beware: if you do a breaking changes in |common_inputs.tex| (e.g.\ redefine |42| to |43|), then the previously cached picture will not be recompiled! (So you will still read 42 instead of 43.)
-\subsection{Disabling externalization}\label{sec:disableExternalization}
+\subsection{Wrap arbitrary environments}
-You can use |disable externalization| to disable externalization (which is particularly practical if you set |\robExtExternalizeAllTikzpictures|). You can configure the exact command run in that case using |command if no externalization/.code={...}|, see \cref{sec:disableExternalization} for details.
+You can wrap arbitrary environments using the already presented |cacheEnvironment| and |cacheCommand|, where the first mandatory argument is the name of the environment/macro, and the second mandatory argument contains the default preset. |cacheEnvironment| works for any environment while |cacheCommand| might need a bit of help to determine the signature of the macro if the function is defined via xparse. Long story short, |O{foo}| is an optional argument with default value foo, |m| is a mandatory argument. By default, you can pass an optional arguments via the first argument enclosed in |<>|:
+\begin{codeexample}[width=0pt,vbox]
+ \cacheCommand{zx}[O{}O{}O{}m]{latex, add to preamble={\usepackage{zx-calculus}\def\hello#1{Hello #1.}}}
+ \zx<add to preamble={\usepackage{amsmath}\def\bye#1{Bye #1.}}>[mbr=1]{ % amsmath provides \text
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ{\text{\hello{Alice}}} \\
+ \zxZ{\beta} \rar & \zxZ{\text{\bye{Bob}}}
+ }
+\end{codeexample}
+
+you can also disable externalization for some commands using this same command, here is for instance the code to use |todonotes|:
+\begin{codeexample}[code only]
+\cacheCommand{todo}[O{}m]{disable externalization}
+\todo{Check how to use cacheCommand and cacheEnvironment}
+\end{codeexample}
+
+Which gives you {
+ \cacheCommand{todo}[O{}m]{disable externalization}
+ \todo{Check how to use cacheCommand and cacheEnvironment}
+}
+
+
+See \cref{sec:wrapAutomatically} for more details.
+
+\subsection{Disabling externalization}
+
+You can use |disable externalization| to disable externalization (which is particularly practical if you set |\cacheTikz|). You can configure the exact command run in that case using |command if no externalization/.code={...}|, but most of the time it should work out of the box (see \cref{sec:disableExternalization} for details).
\begin{codeexample}[width=0pt,vbox]
% In theory all pictures should be externalized (so remember picture should fail)
\tikz[remember picture,baseline=(pointtome1.base)]
\node[rounded corners, fill=orange](pointtome1){Point to me if you can};\\
- \robExtExternalizeAllTikzpictures
+ \cacheTikz
% But we can disable it temporarily
- \begin{tikzpicture}[remember picture][disable externalization]
+ \begin{tikzpicture}<disable externalization>[remember picture]
\node[rounded corners, fill=red](A){This figure is not externalized.
This way, it can use remember picture.};
\draw[->,overlay] (A) to[bend right] (pointtome1);
@@ -355,17 +646,38 @@ You can use |disable externalization| to disable externalization (which is parti
\end{tikzpicture}
\end{codeexample}
+You can also disable externalization for some kinds of commands. For instance, the package |todonotes| requires |remember picture| and is therefore not compatible with externalization provided by this package. To disable externalization on all |\todo|, you can do:
+
+\begin{codeexample}[code only]
+\cacheCommand{todo}[O{}m]{disable externalization}
+\todo{Check how to use cacheCommand and cacheEnvironment}
+\end{codeexample}
+
+Which gives you {
+ \cacheCommand{todo}[O{}m]{disable externalization}
+ \todo{Check how to use cacheCommand and cacheEnvironment}
+}
+
\subsection{Feeding data from the main document to the picture}
You can feed data from the main document to the cached file using placeholders, since |set placeholder eval={__foo__}{\bar}| will evaluate |\bar| and put the result in |__foo__|. For instance, if the picture depends on the current page, you can do:
\begin{codeexample}[width=0pt,vbox]
-\begin{tikzpictureC}[][set placeholder eval={__thepage__}{\thepage}]
+\begin{tikzpictureC}<set placeholder eval={__thepage__}{\thepage}>
\node[rounded corners, fill=red]{The current page is __thepage__.};
\end{tikzpictureC}
\end{codeexample}
+\subsection{Defining macros}
+
+You can define macros in the preamble:
+\begin{codeexample}[width=0pt,vbox]
+\cacheMe[latex, add to preamble={\def\sayhello#1{Hello #1.}}]{
+ \sayhello{my friend}
+}
+\end{codeexample}
+
\subsection{Feeding data back into the main document}
For more advanced usage, you might want to compute a data and cache the result in a macro that you could use later. This is possible if you write into the file |\jobname-out.tex| during the compilation of the cached file (by default, we already open |\writeRobExt| to write to this file). This file will be automatically loaded before loading the pdf (but you can customize all these operations, for instance if you do not want to load the pdf at all; the only requirement is that you should generate a |.pdf| file to specify that the compilation is finished).
@@ -388,6 +700,38 @@ We compute this data that is long to compute:
We computed the cached value \myLongResult.
\end{codeexample}
+\subsection{Compile a preset}\label{sec:compilePreset}
+
+Long story short: you can compile even faster (around 1.5x in our tests) by compiling presets, but beware that you will not be able to modify the placeholders except |add to preamble| with the default compiler we provide:
+
+\begin{codeexample}[vbox]
+ % We create a latex-based preset and compile it
+\robExtConfigure{
+ new preset={templateZX}{
+ latex,
+ add to preamble={
+ \usepackage{tikz}
+ \usepackage{tikz-cd}
+ \usepackage{zx-calculus}
+ },
+ %% possibly add some dependencies
+ },
+ % We compile it into a new preset
+ new compiled preset={compiled ZX}{templateZX, compile latex template}{},
+}
+
+% we use that preset automatically for ZX environments
+\cacheEnvironment{ZX}{compiled ZX}
+\cacheCommand{zx}{compiled ZX}
+
+% Usage: (you can't use placeholders except for the preamble, trade-off of the compiled template)
+\begin{ZX}<add to preamble={\def\sayHey#1{Hey #1!}}>
+ \zxX{\sayHey{Bob}}
+\end{ZX}
+\end{codeexample}
+
+For details, see \cref{sec:compileFaster}.
+
\subsection{For non-\LaTeX{} code}
Due to the way \LaTeX{} works, non-\LaTeX{} code can't be reliably read inside macros and some environments that parse their body (e.g. align) as some characters are removed (e.g. percent symbols are comments and are removed). For this reason, we sometimes need to separate the time where we define the code and where we insert it (this is done using placeholders, see |PlaceholderFromCode|), and we need to introduce new environments to populate the template (see \cref{sec:placeholders} for more details, to generate them from filename, to get the path of a file etc).
@@ -445,7 +789,7 @@ $\rightarrow$ The cosinus of 1 is \cosComputedInPython.
\paragraph{Improve an existing preset}
-If you often use the same code (e.g.\ load matplotlib, save the file etc), you can directly modify the |__ROBEXT_MAIN_CONTENT__| placeholder to add the redundant information (or create a new template from scratch, see below), as this placeholder contains the code typed by the user (this is true for all presets, as |CacheMe*| is in charge of setting this placeholder):
+If you often use the same code (e.g.\ load matplotlib, save the file etc), you can directly modify the |__ROBEXT_MAIN_CONTENT__| placeholder to add the redundant information (or create a new template from scratch, see below). By default, it points to |__ROBEXT_MAIN_CONTENT_ORIG__| that contains directly the code typed by the user (this is true for all presets, as |CacheMe*| is in charge of setting this placeholder). When dealing with \LaTeX{} code, |__ROBEXT_MAIN_CONTENT__| should ideally contain a code that can be inserted as-it in the document in order to be compatible by default with |disable externalization|. So if you want to wrap the content of the user in an environment like |\begin{tikzpicture}...\end{tikzpicture}|, this is the placeholder to modify.
\begin{codeAndResult}
%% Create your style:
@@ -459,7 +803,7 @@ plt.savefig("__ROBEXT_OUTPUT_PDF__")
\end{PlaceholderFromCode}
\robExtConfigure{
- my matplotlib/.style={
+ new preset={my matplotlib}{
python,
add before placeholder no space={__ROBEXT_MAIN_CONTENT__}{__MY_MATPLOTLIB_TEMPLATE_BEFORE__},
add to placeholder no space={__ROBEXT_MAIN_CONTENT__}{__MY_MATPLOTLIB_TEMPLATE_AFTER__},
@@ -496,7 +840,7 @@ plt.savefig("__ROBEXT_OUTPUT_PDF__")
\end{PlaceholderFromCode}
\robExtConfigure{
- my matplotlib/.style={
+ new preset={my matplotlib}{
python,
% We create a new placeholder (it is simple enough that you don't need to use PlaceholderFromCode)
set placeholder={__MY_MATPLOTLIB_FONT_SIZE__}{12},
@@ -573,12 +917,12 @@ print_file.close()
\end{PlaceholderFromCode}
\robExtConfigure{
- my python print both/.style={
+ new preset={my python print both}{
python,
add before placeholder no space={__ROBEXT_MAIN_CONTENT__}{__MY_PRINT_BOTH_TEMPLATE_BEFORE__},
add to placeholder no space={__ROBEXT_MAIN_CONTENT__}{__MY_PRINT_BOTH_TEMPLATE_AFTER__},
set title/.style={
- set placeholder={__MY_TITLE__}{##1},
+ set placeholder={__MY_TITLE__}{#1},
},
set title={Example},
custom include command={
@@ -644,12 +988,12 @@ print_file.close()
\end{PlaceholderFromCode}
\robExtConfigure{
- my python print both/.style={
+ new preset={my python print both}{
python,
add before placeholder no space={__ROBEXT_MAIN_CONTENT__}{__MY_PRINT_BOTH_TEMPLATE_BEFORE__},
add to placeholder no space={__ROBEXT_MAIN_CONTENT__}{__MY_PRINT_BOTH_TEMPLATE_AFTER__},
set title/.style={
- set placeholder={__MY_TITLE__}{##1},
+ set placeholder={__MY_TITLE__}{#1},
},
set title={Example},
custom include command={
@@ -674,7 +1018,7 @@ for name in ["Alice", "Bob"]:
\end{CacheMeCode}
}
-\subsubsection{Other languages}
+\subsubsection{Other languages}\label{sec:otherLanguages}
We also provide support for other languages, notably |bash|, but it is relatively easy to add basic support for any new language. You only need to configure |set compilation command| to your command, |set template| to the file to compile (|__ROBEXT_MAIN_CONTENT__| contains the code typed by the user), and possibly a custom include command with |custom include command| if you do not want to do |\includegraphics| on the final pdf. For instance, to define a basic template for bash, you just need to use:
@@ -689,7 +1033,7 @@ touch "__ROBEXT_OUTPUT_PDF__"
\end{PlaceholderFromCode}
\robExtConfigure{
- my bash/.style={
+ new preset={my bash}{
set compilation command={bash "__ROBEXT_SOURCE_FILE__"},
set template={__MY_BASH_TEMPLATE__},
%%% Version 1:
@@ -715,7 +1059,7 @@ uname -srv > "__ROBEXT_OUTPUT_PREFIX__-out.txt"
\paragraph{Code inside a macro}
-Due to fundamental \LaTeX{} restrictions, it is impossible to use |CacheMeCode| inside a macro or some environments as \LaTeX{} will strip all lines containing a percent character for instance. The solution here is to define our main content before, and then set it using |set main content| (that simply sets |__ROBEXT_MAIN_CONTENT__|). In this example, we also show how |CacheMeNoContent| can be used when their is no content (the arguments to |CacheMe| are directly given in the body of |CacheMeNoContent|):
+Due to fundamental \LaTeX{} restrictions, it is impossible to use |CacheMeCode| inside a macro or some environments as \LaTeX{} will strip all lines containing a percent character for instance. The solution here is to define our main content before, and then set it using |set main content| (that simply sets |__ROBEXT_MAIN_CONTENT_ORIG__|). In this example, we also show how |CacheMeNoContent| can be used when their is no content (the arguments to |CacheMe| are directly given in the body of |CacheMeNoContent|):
\begin{codeAndResult}
\begin{PlaceholderFromCode}{__TMP_MAIN_CONTENT__}
@@ -756,9 +1100,9 @@ Note also that we usually define two names for each function, one normal and one
\subsection{Placeholders}\label{sec:placeholders}
-Placeholders are the main concept allowing this library to generate the content of a source file based on a template (a template will itself be a placeholder containing other placeholders). A placeholder is a special strings like |__COLOR_IMAGE__| inserted for instance in a string, that will be given a value later. This value will be used to replace (recursively) the placeholder in the template. For instance, if a placeholder |__LIKES__| contains |I like __FRUIT__ and __VEGETABLE__|, if the placeholder |__FRUIT__| contains |oranges| and if the placeholder |__VEGETABLE__| contains |salad|, then evaluating |__LIKES__| will output |I like oranges and salad.|
+Placeholders are the main concept allowing this library to generate the content of a source file based on a template (a template will itself be a placeholder containing other placeholders). A placeholder is a special strings like |__COLOR_IMAGE__| that should start and end with two underscores, ideally containing no space or double underscores inside the name directly. Placeholders are inserted for instance in a string and will be given a value later. This value will be used to replace (recursively) the placeholder in the template. For instance, if a placeholder |__LIKES__| contains |I like __FRUIT__ and __VEGETABLE__|, if the placeholder |__FRUIT__| contains |oranges| and if the placeholder |__VEGETABLE__| contains |salad|, then evaluating |__LIKES__| will output |I like oranges and salad.|
-Note that the usage of underscore in only a convention, as any name can be used for the placeholder. There is however one rule to follow: the name of a placeholder should be made to avoid ambiguities when replacing the string, notably its name should not contain the name of another placeholder. For instance, if we define a placeholder called |NAME| containing |Foo| and a placeholder named |FULL_NAME| containing |Foo Bar|, then when evaluating the string |My name is FULL_NAME|, we have no way to know if the user wants to get |My name is FULL_Foo| or |My name is Foo Bar|. For this reason, \textbf{we advice users to start and end their placeholder names using two underscores} |__|, while using only upper case letters and single underscore |_| inside the placeholder name (this also improves readability). If you are worried about ambiguities like |__PLACEHOLDER1__PLACEHOLDER2__|, you can also use different separators for the beginning and the end like |__PLACEHOLDER1__|, but beware that |[| requires brackets around when used in pgf styles.
+Note that you are not strictly forced to follow the above convention (it allows us to optimize the code to find and replace placeholders), but in that case you should enable |not all placeholders have underscores|.
Placeholders are local variables (internally just some \LaTeX{} 3 strings). You can therefore define a placeholder in a local group surrounded by brackets |{ ... }| if you want it to have a reduced scope.
@@ -767,14 +1111,15 @@ Placeholders are local variables (internally just some \LaTeX{} 3 strings). You
\begin{pgfmanualentry}
\extractcommand\getPlaceholder\opt{\oarg{new placeholder name}}\marg{name placeholder or string}\@@
\extractcommand\getPlaceholderInResult\opt{\oarg{new placeholder name}}\marg{name placeholder or string}\@@
+ \extractcommand\getPlaceholderInResultFromList\marg{list,of,placeholders,to,replace}\opt{\oarg{new placeholder name}}\marg{name placeholder or string}\@@
\pgfmanualbody
Get the value of a placeholder after replacing (recursively) all the inner placeholders. |\getPlaceholderInResult| puts the resulting string in a \LaTeX{} 3 string |\l_robExt_result_str| and in |\robExtResult|, while |\getPlaceholder| directly outputs this string. You can also put inside the argument
any arbitrary string, allowing you, for instance, to concatenate multiple placeholders, copy a placeholder etc. Note that you will get a string, but this string will not be evaluated by \LaTeX{} (see |\evalPlaceholder| for that), for instance math will not be interpreted:
\begin{codeexample}[width=0pt,vbox]
- \placeholderFromContent{__MY_PLACEHOLDER__}{Hello __NAME__, I am a template $\delta_n$.}
- \placeholderFromContent{__NAME__}{Alice __NICKNAME__}
- \placeholderFromContent{__NICKNAME__}{the great}
+ \setPlaceholder{__MY_PLACEHOLDER__}{Hello __NAME__, I am a template $\delta_n$.}
+ \setPlaceholder{__NAME__}{Alice __NICKNAME__}
+ \setPlaceholder{__NICKNAME__}{the great}
The placeholder evaluates to:\\
\texttt{\getPlaceholder{__MY_PLACEHOLDER__}}\\
Combining placeholders produces:\\
@@ -782,11 +1127,22 @@ Placeholders are local variables (internally just some \LaTeX{} 3 strings). You
\end{codeexample}
You can also specify the optional argument in order to additionally define a new placeholder containing the resulting string (but you might prefer to use its alias |\setPlaceholderRec| described below):
\begin{codeexample}[width=0pt,vbox]
- \placeholderFromContent{__MY_PLACEHOLDER__}{Hello __NAME__, I am a template $\delta_n$.}
- \placeholderFromContent{__NAME__}{Alice __NICKNAME__}
- \placeholderFromContent{__NICKNAME__}{the great}
+ \setPlaceholder{__MY_PLACEHOLDER__}{Hello __NAME__, I am a template $\delta_n$.}
+ \setPlaceholder{__NAME__}{Alice __NICKNAME__}
+ \setPlaceholder{__NICKNAME__}{the great}
\getPlaceholderInResult[__NEW_PLACEHOLDER__]{In ``__MY_PLACEHOLDER__'', the name is __NAME__.}
- \printAllPlaceholdersExceptDefaults
+ \printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+The variation |\getPlaceholderInResultFromList| allows you to specify a set of placeholder to replace from:
+\begin{codeexample}[width=0pt,vbox]
+\setPlaceholder{__MY_PLACEHOLDER__}{Hello __NAME1__, __NAME2__ and __NAME3__, I am a template $\delta_n$.}
+\setPlaceholder{__NAME1__}{Alice}
+\setPlaceholder{__NAME2__}{Bob}
+\setPlaceholder{__NAME3__}{Charlie}
+\getPlaceholderInResultReplaceFromList{__MY_PLACEHOLDER__,__NAME1__,__NAME2__}[__NEW_PLACEHOLDER__]{
+ Here we go: __MY_PLACEHOLDER__
+}
+\printImportedPlaceholdersExceptDefaults
\end{codeexample}
\end{pgfmanualentry}
@@ -797,9 +1153,9 @@ You can also specify the optional argument in order to additionally define a new
Evaluate the value of a placeholder after replacing (recursively) all the inner placeholders. You can also put inside any arbitrary string.
\begin{codeexample}[width=0pt,vbox]
- \placeholderFromContent{__MY_PLACEHOLDER__}{Hello __NAME__, I am a template $\delta_n$.}
- \placeholderFromContent{__NAME__}{Alice __NICKNAME__}
- \placeholderFromContent{__NICKNAME__}{the great}
+ \setPlaceholder{__MY_PLACEHOLDER__}{Hello __NAME__, I am a template $\delta_n$.}
+ \setPlaceholder{__NAME__}{Alice __NICKNAME__}
+ \setPlaceholder{__NICKNAME__}{the great}
% The placeholder evaluates to \texttt{\getPlaceholder{__MY_PLACEHOLDER__}}.
The placeholder evaluates to:\\
\evalPlaceholder{__MY_PLACEHOLDER__}\\
@@ -808,47 +1164,54 @@ You can also specify the optional argument in order to additionally define a new
\end{codeexample}
\end{pgfmanualentry}
-\subsubsection{List and debug placeholders}
+\subsubsection{List and debug placeholders}\label{sec:listAndDebugPlaceholders}
-It can sometimes be handy to list all placeholders, print their contents etc. We list here commands that are mostly useful for debugging purposes.
+It can sometimes be handy to list all placeholders, print their contents etc (see also \cref{sec:debug}). We list here commands that are mostly useful for debugging purposes.
\begin{pgfmanualentry}
- \extractcommand\printAllPlaceholdersExceptDefaults\opt{*}\@@
+ \extractcommand\printImportedPlaceholdersExceptDefaults\opt{*}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/print imported placeholders except default\@nil
+ \makeatother%
\pgfmanualbody
- Prints the verbatim content of all defined placeholders (without performing any replacement of inner placeholders), except for the placeholders that are defined by default in this library (that we identify as they start with |__ROBEXT_|). The stared version does print the name of the placeholder defined in this library, but not their definition. This is mostly for debugging purposes.
+ Prints the verbatim content of all defined and imported placeholders (without performing any replacement of inner placeholders), except for the placeholders that are defined by default in this library (that we identify as they start with |__ROBEXT_|). The stared version does print the name of the placeholder defined in this library, but not their definition. This is mostly for debugging purposes.
\begin{codeexample}[width=0pt,vbox]
\placeholderFromContent{__LIKES__}{Hello __NAME__ I am a really basic template $\delta_n$.}
\placeholderFromContent{__NAME__}{Alice}
-\printAllPlaceholdersExceptDefaults
+\printImportedPlaceholdersExceptDefaults
\end{codeexample}
Compare with:
\begin{codeexample}[width=0pt,vbox]
\placeholderFromContent{__LIKES__}{Hello __NAME__ I am a really basic template $\delta_n$.}
\placeholderFromContent{__NAME__}{Alice}
-\printAllPlaceholdersExceptDefaults*
+\printImportedPlaceholdersExceptDefaults*
\end{codeexample}
\end{pgfmanualentry}
\begin{pgfmanualentry}
- \extractcommand\printAllPlaceholders\@@
+ \extractcommand\printImportedPlaceholders\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/print imported placeholders\@nil
+ \makeatother%
\pgfmanualbody
- Prints the verbatim content of all defined placeholders (without performing any replacement of inner placeholders), including the placeholders that are defined by default in this library. This is mostly for debugging purposes. Here is the result of |\printAllPlaceholders|:
+ Prints the verbatim content of all defined and imported placeholders (without performing any replacement of inner placeholders), including the placeholders that are defined by default in this library (those starting with |__ROBEXT_|). This is mostly for debugging purposes. Here is the result of |\printImportedPlaceholders|:
- \printAllPlaceholders
+ \printImportedPlaceholders
\end{pgfmanualentry}
-
\begin{pgfmanualentry}
\extractcommand\printPlaceholderNoReplacement\marg{name placeholder}\@@
\pgfmanualbody
Prints the verbatim content of a given placeholder, without evaluating it and \textbf{without replacing inner placeholders: it is used mostly for debugging purposes} and will be used in this documentation to display the content of the placeholder for educational purposes. The stared version prints it inline.
\begin{codeexample}[width=0pt,vbox]
- \placeholderFromContent{__LIKES__}{Hello NAME I am a really basic template $\delta_n$.}
- \placeholderFromContent{NAME}{Alice}
+ \placeholderFromContent{__LIKES__}{Hello __NAME__ I am a really basic template $\delta_n$.}
+ \placeholderFromContent{__NAME__}{Alice}
The (unexpanded) template contains \printPlaceholderNoReplacement{__LIKES__}.\\
The (unexpanded) template contains \printPlaceholderNoReplacement*{__LIKES__}
\end{codeexample}
@@ -860,8 +1223,8 @@ Compare with:
Like |\printPlaceholderNoReplacement| except that it first replaces the inner placeholders. The stared version prints it inline.
\begin{codeexample}[width=0pt,vbox]
- \placeholderFromContent{__LIKES__}{Hello NAME I am a really basic template $\delta_n$.}
- \placeholderFromContent{NAME}{Alice}
+ \placeholderFromContent{__LIKES__}{Hello __NAME__ I am a really basic template $\delta_n$.}
+ \placeholderFromContent{__NAME__}{Alice}
The (unexpanded) template contains \printPlaceholder{__LIKES__}.\\
The (unexpanded) template contains \printPlaceholder*{__LIKES__}
\end{codeexample}
@@ -873,20 +1236,25 @@ Compare with:
Evaluates the content of a given placeholder as a \LaTeX{} code, \textbf{without replacing the placeholders contained inside (mostly used for debugging purposes).}
\begin{codeexample}[width=0pt,vbox]
- \placeholderFromContent{__LIKES__}{Hello NAME I am a really basic template $\delta_n$.}
- \placeholderFromContent{NAME}{Alice}
+ \placeholderFromContent{__LIKES__}{Hello I am a really basic template $\delta_n$.}
The (unexpanded) template evaluates to ``\evalPlaceholderNoReplacement{__LIKES__}''.
\end{codeexample}
\end{pgfmanualentry}
\begin{pgfmanualentry}
+ \extractcommand\rescanPlaceholderInVariableNoReplacement\marg{name macro}\marg{name placeholder}\@@
+ \pgfmanualbody
+ (new v2.0) Create a new macro that executes the \LaTeX{} code in the placeholder.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
\extractcommand\getPlaceholderNoReplacement\marg{name placeholder}\@@
\pgfmanualbody
Like |\evalPlaceholderNoReplacement| except that it only outputs the string without evaluating the macros inside.
\begin{codeexample}[width=0pt,vbox]
- \placeholderFromContent{__LIKES__}{Hello NAME I am a really basic template $\delta_n$.}
- \placeholderFromContent{NAME}{Alice}
+ \placeholderFromContent{__LIKES__}{Hello __NAME__ I am a really basic template $\delta_n$.}
+ \placeholderFromContent{__NAME__}{Alice}
The (unexpanded) template contains \texttt{\getPlaceholderNoReplacement{__LIKES__}}
\end{codeexample}
\end{pgfmanualentry}
@@ -895,11 +1263,12 @@ Compare with:
\begin{pgfmanualentry}
- \extractcommand\placeholderFromContent\marg{name placeholder}\marg{content placeholder}\@@
- \extractcommand\setPlaceholder\marg{name placeholder}\marg{content placeholder}\@@
+ \extractcommand\placeholderFromContent\opt{*}\marg{name placeholder}\marg{content placeholder}\@@
+ \extractcommand\setPlaceholder\opt{*}\marg{name placeholder}\marg{content placeholder}\@@
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/set placeholder=\marg{name placeholder}\marg{content placeholder}\@nil
+ \extractkey/robExt/set placeholder no import=\marg{name placeholder}\marg{content placeholder}\@nil
\extractkey/robExt/set placeholder from content=\marg{name placeholder}\marg{content placeholder}\@nil
\makeatother%
\pgfmanualbody
@@ -915,93 +1284,10 @@ Compare with:
As you can see, \textbf{the precise content is not exactly identical to the original string}: \LaTeX{} comments are removed, spaces are added after macros, some newlines are removed etc. While this is usually not an issue when dealing with \LaTeX{} code, it causes some troubles when dealing with non-\LaTeX{} code. For this reason, we define \textbf{other commands} (see for instance |PlaceholderFromCode| below) that can accept verbatim content; the downside being that \LaTeX{} forbids usage of these verbatim commands inside other macros, so you should always define them at the top level (this seems to be fundamental to how \LaTeX{} works, as any input to a macro gets interpreted first as a \LaTeX{} string, losing all comments for instance). Note that this is not as restrictive as it may sound, as it is always possible to define the needed placeholders before any macro, while using them inside the macro, possibly combining them with other placeholders (defined either before or inside the macro).
\end{pgfmanualentry}
-But before seeing how to define placeholder containing arbitrary code, let us first see how we can define a placeholder recursively, by giving it a value based on its previous value (useful for instance in order to add stuff to it).
-
-\begin{pgfmanualentry}
- \extractcommand\setPlaceholderRec\marg{new placeholder}\marg{content with placeholder}\@@
- \makeatletter%
- \def\extrakeytext{style, }
- \extractkey/robExt/set placeholder rec=\marg{name placeholder}\marg{content placeholder}\@nil
- \makeatother%
- \pgfmanualbody
-
- |\setPlaceholderRec{foo}{bar}| is actually an alias for |\getPlaceholderInResult[foo]{bar}|. Note that contrary to |\setPlaceholder|, it recursively replaces all inner placeholders. This is particularly useful to add stuff to an existing (or not) placeholder:
-\begin{codeexample}[width=0pt,vbox]
-\setPlaceholderRec{__MY_COMMAND__}{pdflatex}
-\setPlaceholderRec{__MY_COMMAND__}{__MY_COMMAND__ myfile}
-\printAllPlaceholdersExceptDefaults
-\end{codeexample}
-Note that the if the placeholder content contains at the end the placeholder name, we will automatically remove it to avoid infinite recursion at evaluation time. This has the benefit that you can add something to a placeholder even if this placeholder does not exists yet (in which case it will be understood as the empty string):
-\begin{codeexample}[width=0pt,vbox]
-\setPlaceholderRec{__COMMAND_ARGS__}{__COMMAND_ARGS__ -l}
-\setPlaceholderRec{__COMMAND_ARGS__}{__COMMAND_ARGS__ -s}
-\printAllPlaceholdersExceptDefaults
-\end{codeexample}
-\end{pgfmanualentry}
-
-Note that sometimes, you might not want to use |\setPlaceholderRec| to simply append some data to the placeholder as it will also evaluate the inner placeholders (meaning that you will not be able to redefine them later). For this reason, we also provide functions to add something to the placeholder without evaluating it first:
-\begin{pgfmanualentry}
- \extractcommand\addToPlaceholder\opt{*}\marg{placeholder}\marg{content to add}\@@
- \extractcommand\addBeforePlaceholder\opt{*}\marg{placeholder}\marg{content to add}\@@
- \makeatletter%
- \def\extrakeytext{style, }
- \extractkey/robExt/add to placeholder=\marg{name placeholder}\marg{content to add}\@nil
- \extractkey/robExt/add to placeholder no space=\marg{name placeholder}\marg{content to add}\@nil
- \extractkey/robExt/add before placeholder=\marg{name placeholder}\marg{content to add}\@nil
- \extractkey/robExt/add before placeholder no space=\marg{name placeholder}\marg{content to add}\@nil
- \makeatother%
- \pgfmanualbody
-
- |\addToPlaceholder{foo}{bar}| adds |bar| at the end of the placeholder |foo| (by default it also adds a space, unless you use the star version), creating it if it does not exist (the |before| variants add the content\dots{} before).
-\begin{codeexample}[width=0pt,vbox]
-\setPlaceholder{__ENGINE__}{pdflatex}
-\setPlaceholder{__COMMAND__}{__ENGINE__ --option}
-\addToPlaceholder{__COMMAND__}{--other}
-\addToPlaceholder*{__COMMAND__}{-option}
-\addBeforePlaceholder{__COMMAND__}{time}
-\printAllPlaceholdersExceptDefaults
-\end{codeexample}
-\end{pgfmanualentry}
-
\begin{pgfmanualentry}
- \extractcommand\evalPlaceholderInplace\marg{name placeholder}\@@
- \makeatletter%
- \def\extrakeytext{style, }
- \extractkey/robExt/eval placeholder inplace=\marg{name placeholder}\@nil
- \makeatother%
- \pgfmanualbody
- This command will update (inplace) the content of a macro by first replacing recursively the placeholders, and finally by expanding the \LaTeX{} macros.
-\begin{codeexample}[width=0pt,vbox]
-\def\mymacro{Initial value}
-\placeholderFromContent{__MACRO_NOT_EVALUATED__}{\mymacro}
-\placeholderFromContent{__MACRO_EVALUATED__}{\mymacro}
-\evalPlaceholderInplace{__MACRO_EVALUATED__}
-\printAllPlaceholdersExceptDefaults
-\def\mymacro{Final value}
-Compare \evalPlaceholder{__MACRO_EVALUATED__} and \evalPlaceholder{__MACRO_NOT_EVALUATED__}.
-\end{codeexample}
-\end{pgfmanualentry}
-
-\begin{pgfmanualentry}
- \makeatletter%
- \def\extrakeytext{style, }
- \extractkey/robExt/set placeholder eval=\marg{name placeholder}\marg{content placeholder}\@nil
- \makeatother%
- \pgfmanualbody
- Alias for |\setPlaceholderRec{#1}{#2}\evalPlaceholderInplace{#1}|: set and evaluate recursively the placeholders and macros. This can be practical to pass the value of a counter/macro to the template (of course, if this value is fixed, you can also directly load it from the preambule):
-\begin{codeexample}[width=0pt,vbox]
-\begin{CacheMe}{tikz, set placeholder eval={__thepage__}{\thepage}}
- \node[rounded corners, fill=red]{The current page is __thepage__.};
-\end{CacheMe}
-\end{codeexample}
-Note that this works well for commands that expand completely, but some more complex commands might not expand properly (like |cref|). I need to investigate how to solve this issue, meanwhile you can still disable externalization for these pictures.
-\end{pgfmanualentry}
-
-
-\begin{pgfmanualentry}
- \extractenvironement{PlaceholderFromCode}\marg{name placeholder}\@@
- \extractenvironement{setPlaceholderCode}\marg{name placeholder}\@@
+ \extractenvironement{PlaceholderFromCode}\opt{*}\marg{name placeholder}\@@
+ \extractenvironement{SetPlaceholderCode}\opt{*}\marg{name placeholder}\@@
\pgfmanualbody
These two (aliased) environments are useful to set a verbatim value to a given placeholder: the advantage is that you can put inside any code, including \LaTeX{} comments, the downside is that you cannot use it inside macros and some environments (so you typically define it before the macros and call it inside).
@@ -1018,7 +1304,7 @@ def my_function(b): # this is a python code
d[42] = 0
return b
\end{PlaceholderFromCode}
-\printAllPlaceholdersExceptDefaults
+\printImportedPlaceholdersExceptDefaults
\end{codeexample}
@@ -1030,7 +1316,7 @@ def my_function(b): # this is a python code
d[42] = 0
return b % 2
\end{PlaceholderFromCode}
-\printAllPlaceholdersExceptDefaults
+\printImportedPlaceholdersExceptDefaults
\end{verbatim}
would produce:
@@ -1042,14 +1328,16 @@ def my_function(b): # this is a python code
return b % 2
\end{PlaceholderFromCode}
\begin{codeexample}[width=0pt,vbox]
-\printAllPlaceholdersExceptDefaults
+\printImportedPlaceholdersExceptDefaults
\end{codeexample}
}
Note that of course, you can define a placeholder before a macro and call it inside (explaining how we can generate this documentation).
+
+Note that the star and no import version does NOT import the placeholder it the main group (unless you try to optimize the compilation time you should not need it, but see \cref{sec:importSystem} for details).
\end{pgfmanualentry}
\begin{pgfmanualentry}
- \extractcommand\placeholderPathFromFilename\marg{name placeholder}\marg{filename}\@@
+ \extractcommand\placeholderPathFromFilename\opt{*}\marg{name placeholder}\marg{filename}\@@
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/set placeholder path from filename=\marg{name placeholder}\marg{filename}\@nil
@@ -1059,49 +1347,54 @@ Note that of course, you can define a placeholder before a macro and call it ins
|\placeholderPathFromFilename{__MYLIB__}{mylib.py}| will copy |mylib.py| in the cache (setting its hash depending on its content), and set the content of the placeholder |__MYLIB__| to the \textbf{path} of the library in the cache. Note that the path is relative to the cache folder (it is easier to use for instance if you want to call this library from a code already in the cache).
\begin{codeexample}[width=0pt,vbox]
\placeholderPathFromFilename{__MYLIB__}{mylib.py}
- \printAllPlaceholdersExceptDefaults
+ \printImportedPlaceholdersExceptDefaults
You can also get the path relative to the root folder:\\
\robExtAddCachePath{\getPlaceholderNoReplacement{__MYLIB__}}
\end{codeexample}
+Note that the star and no import version does NOT import the placeholder it the main group (unless you try to optimize the compilation time you should not need it, but see \cref{sec:importSystem} for details).
\end{pgfmanualentry}
\begin{pgfmanualentry}
- \extractcommand\placeholderFromFileContent\marg{name placeholder}\marg{filename}\@@
+ \extractcommand\placeholderFromFileContent\opt{*}\marg{name placeholder}\marg{filename}\@@
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/set placeholder from file content=\marg{name placeholder}\marg{filename}\@nil
+ \extractkey/robExt/set placeholder from file content no import=\marg{name placeholder}\marg{filename}\@nil
\makeatother%
\pgfmanualbody
|\placeholderFromFileContent{__MYLIB__}{mylib.py}| will set the content of the placeholder |__MYLIB__| to the content of |mylib.py|.
\begin{codeexample}[width=0pt,vbox]
\placeholderFromFileContent{__MYLIB__}{mylib.py}
- \printAllPlaceholdersExceptDefaults
+ \printImportedPlaceholdersExceptDefaults
\end{codeexample}
+Note that the star and no import version does NOT import the placeholder it the main group (unless you try to optimize the compilation time you should not need it, but see \cref{sec:importSystem} for details).
\end{pgfmanualentry}
\begin{pgfmanualentry}
- \extractcommand\placeholderPathFromContent\marg{name placeholder}\opt{\oarg{suffix}}\marg{content}\@@
+ \extractcommand\placeholderPathFromContent\opt{*}\marg{name placeholder}\opt{\oarg{suffix}}\marg{content}\@@
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/set placeholder path from content=\marg{name placeholder}\marg{suffix}\marg{content}\@nil
+ \extractkey/robExt/set placeholder path from content no import=\marg{name placeholder}\marg{suffix}\marg{content}\@nil
\makeatother%
\pgfmanualbody
|\placeholderPathFromContent{__MYLIB__}{some content}| will copy |some content| in a file in the cache (setting its hash depending on its content, the filename will end with |suffix| that defaults to |.tex|), and set the content of the placeholder |__MYLIB__| to the \textbf{path} of the file in the cache. Note that the path is relative to the cache folder (it is easier to use for instance if you want to call this library from a code already in the cache).
\begin{codeexample}[width=0pt,vbox]
\placeholderPathFromContent{__MYLIB__}[.py]{some contents b}
- \printAllPlaceholdersExceptDefaults
+ \printImportedPlaceholdersExceptDefaults
You can also get the path relative to the root folder:\\
\robExtAddCachePath{\getPlaceholderNoReplacement{__MYLIB__}}\\
As a sanity check, this file contains
\verbatiminput{\robExtAddCachePath{\getPlaceholderNoReplacement{__MYLIB__}}}
\end{codeexample}
+Note that the star and no import version does NOT import the placeholder it the main group (unless you try to optimize the compilation time you should not need it, but see \cref{sec:importSystem} for details).
\end{pgfmanualentry}
\begin{pgfmanualentry}
- \extractenvironement{PlaceholderPathFromCode}\opt{\oarg{suffix}}\marg{name placeholder}\@@
+ \extractenvironement{PlaceholderPathFromCode}\opt{*}\opt{\oarg{suffix}}\marg{name placeholder}\@@
\pgfmanualbody
This environment is similar to |\placeholderPathFromContent| except that it accepts verbatim code (therefore \LaTeX{} comments, newlines etc. will not be removed). However, due to \LaTeX{} limitations, this environment cannot be used inside macros or some environments, or this property will not be preserved.
@@ -1123,20 +1416,22 @@ def my_function(b): # this is a python code
\end{PlaceholderPathFromCode}
You can then use it like:
\begin{codeexample}[width=0pt,vbox]
-\printAllPlaceholdersExceptDefaults
+\printImportedPlaceholdersExceptDefaults
You can also get the path relative to the root folder:\\
\robExtAddCachePath{\getPlaceholderNoReplacement{__MYLIB__}}\\
As a sanity check, this file contains
\verbatiminput{\robExtAddCachePath{\getPlaceholderNoReplacement{__MYLIB__}}}
\end{codeexample}
+Note that the star version does NOT import the placeholder it the main group (unless you try to optimize the compilation time you should not need it, but see \cref{sec:importSystem} for details).
\end{pgfmanualentry}
\begin{pgfmanualentry}
- \extractcommand\copyPlaceholder\marg{new placeholder}\marg{old placeholder}\@@
+ \extractcommand\copyPlaceholder\opt{*}\marg{new placeholder}\marg{old placeholder}\@@
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/copy placeholder=\marg{new placeholder}\marg{old placeholder}\@nil
+ \extractkey/robExt/copy placeholder no import=\marg{new placeholder}\marg{old placeholder}\@nil
\makeatother%
\pgfmanualbody
@@ -1147,9 +1442,438 @@ As a sanity check, this file contains
\setPlaceholder{__MY_CONTENT__}{Some content}
\copyPlaceholder{__MY_OLD_CONTENT__}{__MY_CONTENT__}
\setPlaceholder{__MY_CONTENT__}{The content used to be __MY_OLD_CONTENT__}
- \printAllPlaceholdersExceptDefaults
+ \printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+Note that the star and no import version does NOT import the placeholder it the main group (unless you try to optimize the compilation time you should not need it, but see \cref{sec:importSystem} for details).
+\end{pgfmanualentry}
+
+Now, we see how we can define a placeholder recursively, by giving it a value based on its previous value (useful for instance in order to add stuff to it).
+
+\begin{pgfmanualentry}
+ \extractcommand\setPlaceholderRec\marg{new placeholder}\marg{content with placeholder}\@@
+ \extractcommand\setPlaceholderRecReplaceFromList\marg{list,of,placeholder,to,replace}\marg{new placeholder}\marg{content with placeholder}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/set placeholder rec=\marg{name placeholder}\marg{content placeholder}\@nil
+ \extractkey/robExt/set placeholder rec replace from list=\marg{list,of,placeholder,to,replace}\marg{name placeholder}\marg{content placeholder}\@nil
+ \makeatother%
+ \pgfmanualbody
+
+ |\setPlaceholderRec{foo}{bar}| is actually an alias for |\getPlaceholderInResult[foo]{bar}|. Note that contrary to |\setPlaceholder|, it recursively replaces all inner placeholders. This is particularly useful to add stuff to an existing (or not) placeholder:
+\begin{codeexample}[width=0pt,vbox]
+\setPlaceholderRec{__MY_COMMAND__}{pdflatex}
+\setPlaceholderRec{__MY_COMMAND__}{__MY_COMMAND__ myfile}
+\printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+Note that the if the placeholder content contains at the end the placeholder name, we will automatically remove it to avoid infinite recursion at evaluation time. This has the benefit that you can add something to a placeholder even if this placeholder does not exists yet (in which case it will be understood as the empty string):
+\begin{codeexample}[width=0pt,vbox]
+\setPlaceholderRec{__COMMAND_ARGS__}{__COMMAND_ARGS__ -l}
+\setPlaceholderRec{__COMMAND_ARGS__}{__COMMAND_ARGS__ -s}
+\printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+The variation |\setPlaceholderRecReplaceFromList| allows us to specify a subset of placeholder that will be allowed to be expanded, and is an alias for |\getPlaceholderInResultReplaceFromList| (except that the optional argument is mandatory):
+\begin{codeexample}[width=0pt,vbox]
+\placeholderFromContent{__MY_PLACEHOLDER__}{Hello __NAME1__, __NAME2__ and __NAME3__, I am a template $\delta_n$.}
+\placeholderFromContent{__NAME1__}{Alice}
+\placeholderFromContent{__NAME2__}{Bob}
+\placeholderFromContent{__NAME3__}{Charlie}
+\setPlaceholderRecReplaceFromList{__MY_PLACEHOLDER__,__NAME2__,__NAME3__}{__OTHER_PLACEHOLDER__}{Here we go: __MY_PLACEHOLDER__}
+\printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+Note that the star and no import version does NOT import the placeholder it the main group (unless you try to optimize the compilation time you should not need it, but see \cref{sec:importSystem} for details).
+\end{pgfmanualentry}
+
+Note that sometimes, you might not want to use |\setPlaceholderRec| to simply append some data to the placeholder as it will also evaluate the inner placeholders (meaning that you will not be able to redefine them later). For this reason, we also provide functions to add something to the placeholder without evaluating it first:
+\begin{pgfmanualentry}
+ \extractcommand\addToPlaceholder\opt{*}\marg{placeholder}\marg{content to add}\@@
+ \extractcommand\addToPlaceholderNoImport\opt{*}\marg{placeholder}\marg{content to add}\@@
+ \extractcommand\addBeforePlaceholder\opt{*}\marg{placeholder}\marg{content to add}\@@
+ \extractcommand\addBeforePlaceholderNoImport\opt{*}\marg{placeholder}\marg{content to add}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/add to placeholder=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add to placeholder no space=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add before placeholder=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add before placeholder no space=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add before main content=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add to placeholder no import=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add to placeholder no space no import=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add before placeholder no import=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add before placeholder no space no import=\marg{name placeholder}\marg{content to add}\@nil
+ \extractkey/robExt/add before main content no import=\marg{name placeholder}\marg{content to add}\@nil
+ \makeatother%
+ \pgfmanualbody
+
+ |\addToPlaceholder{foo}{bar}| adds |bar| at the end of the placeholder |foo| (by default it also adds a space, unless you use the star version), creating it if it does not exist (the |before| variants add the content\dots{} before).
+\begin{codeexample}[width=0pt,vbox]
+\setPlaceholder{__ENGINE__}{pdflatex}
+\setPlaceholder{__COMMAND__}{__ENGINE__ --option}
+\addToPlaceholder{__COMMAND__}{--other}
+\addToPlaceholder*{__COMMAND__}{-option}
+\addBeforePlaceholder{__COMMAND__}{time}
+\printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+|add before main content| is a particular case where the placeholder is |__ROBEXT_MAIN_CONTENT__|. It is practical if you want to define for instance a macro, but in a way that even if you disable externalization, the command should still compile (if you define the macro in the preamble, it will not be added when disabling externalization). For instance:
+\begin{codeexample}[width=0pt,vbox]
+\robExtConfigure{
+ new preset={my preset}{latex, add before main content={\def\hello#1{Hello #1.}}},
+}
+\cacheMe[my preset]{Here I am cached (\hello{Alice})} and \cacheMe[my preset, disable externalization]{Here I am not (\hello{Bob}).}
+\end{codeexample}
+The |no import| versions do not import the placeholder in the current group (only needed if you want to optimize the compilation time, see \cref{sec:importSystem} for details).
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\placeholderFromString\opt{*}\marg{latex3 string}\@@
+ \extractcommand\setPlaceholderFromString\opt{*}\marg{latex3 string}\@@
+ \pgfmanualbody
+ (new in v2.0) This allows you to assign an existing \LaTeX{}3 string to a placeholder (the star version does not import the placeholder, see \cref{sec:importSystem}).
+\begin{codeexample}[width=0pt,vbox]
+ \ExplSyntaxOn
+ \setPlaceholderFromString{__my_percent_string__}{\c_percent_str}
+ \printImportedPlaceholdersExceptDefaults
+ \ExplSyntaxOff
+\end{codeexample}
+We provide a list of placeholders that are useful to escape parts of the strings (but you should not really need them, if you need weird characters like percent, most of the time you want to use placeholderFromCode):
+\begin{codeexample}[width=0pt,vbox]
+ \printPlaceholder{
+ String containing
+ __ROBEXT_LEFT_BRACE__,
+ __ROBEXT_RIGHT_BRACE__,
+ __ROBEXT_BACKSLASH__,
+ __ROBEXT_HASH__,
+ __ROBEXT_UNDERSCORE__,
+ __ROBEXT_PERCENT__.
+ }
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\robExtPlaceholderReplaceInplace\marg{placeholder}\marg{from}\marg{to}\@@
+ \extractcommand\robExtPlaceholderReplaceInplaceEval\marg{placeholder}\marg{from}\marg{to}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/placeholder replace in place=\marg{placeholder}\marg{from}\marg{to}\@nil
+ \extractkey/robExt/placeholder replace in place eval=\marg{placeholder}\marg{from}\marg{to}\@nil
+ \makeatother%
+ \pgfmanualbody
+ (new in v2.0) This allows you to replace a value in a placeholder. The |eval| variation first evaluates the string.
+\begin{codeexample}[width=0pt,vbox]
+\def\nameFrom{Bob}
+\def\nameTo{Dylan}
+\robExtConfigure{
+ set placeholder={__NAMES__}{Hello Alice and Bob.},
+ placeholder replace in place={__NAMES__}{Alice}{Charlie},
+ placeholder replace in place eval={__NAMES__}{\nameFrom}{\nameTo},
+}
+\printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\placeholderHalveNumberHashesInplace\marg{placeholder}\@@
+ \extractcommand\placeholderDoubleNumberHashesInplace\marg{placeholder}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/placeholder halve number hashes in place=\marg{placeholder}\@nil
+ \extractkey/robExt/placeholder double number hashes in place=\marg{placeholder}\@nil
+ \makeatother%
+ \pgfmanualbody
+ (new in v2.0) This allows you to either turn any |##| into |#| or the other way around (may be practical when dealing with arguments to functions).
+\begin{codeexample}[width=0pt,vbox]
+\robExtConfigure{
+ set placeholder={__DEMO__}{\def\hey##1{Hey ##1.}},
+ placeholder halve number hashes in place={__DEMO__},
+}
+\printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\removePlaceholder\marg{placeholder}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/remove placeholder=\marg{placeholder}\@nil
+ \extractkey/robExt/remove placeholders=\marg{list,of,placeholder}\@nil
+ \makeatother%
+ \pgfmanualbody
+ (new in v2.0) Remove placeholders.
+\begin{codeexample}[width=0pt,vbox]
+\robExtConfigure{
+ set placeholder={__DEMOA__}{Alice},
+ set placeholder={__DEMOB__}{Bob},
+ set placeholder={__DEMOC__}{Charlie},
+ remove placeholders={__DEMOA__,__DEMOC__},
+}
+\printImportedPlaceholdersExceptDefaults
+\end{codeexample}
+\end{pgfmanualentry}
+
+
+
+\begin{pgfmanualentry}
+ \extractcommand\evalPlaceholderInplace\marg{name placeholder}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/eval placeholder inplace=\marg{name placeholder}\@nil
+ \makeatother%
+ \pgfmanualbody
+ This command will update (inplace) the content of a macro by first replacing recursively the placeholders, and finally by expanding the \LaTeX{} macros.
+\begin{codeexample}[width=0pt,vbox]
+\def\mymacro{Initial value}
+\placeholderFromContent{__MACRO_NOT_EVALUATED__}{\mymacro}
+\placeholderFromContent{__MACRO_EVALUATED__}{\mymacro}
+\evalPlaceholderInplace{__MACRO_EVALUATED__}
+\printImportedPlaceholdersExceptDefaults
+\def\mymacro{Final value}
+Compare \evalPlaceholder{__MACRO_EVALUATED__} and \evalPlaceholder{__MACRO_NOT_EVALUATED__}.
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/set placeholder eval=\marg{name placeholder}\marg{content placeholder}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Alias for |\setPlaceholderRec{#1}{#2}\evalPlaceholderInplace{#1}|: set and evaluate recursively the placeholders and macros. This can be practical to pass the value of a counter/macro to the template (of course, if this value is fixed, you can also directly load it from the preambule):
+\begin{codeexample}[width=0pt,vbox]
+\begin{CacheMe}{tikzpicture, set placeholder eval={__thepage__}{\thepage}}
+ \node[rounded corners, fill=red]{The current page is __thepage__.};
+\end{CacheMe}
+\end{codeexample}
+Note that this works well for commands that expand completely, but some more complex commands might not expand properly (like |cref|). I need to investigate how to solve this issue, meanwhile you can still disable externalization for these pictures.
+\end{pgfmanualentry}
+
+\subsubsection{Groups: the import system}\label{sec:importSystem}
+
+(This whole system was added v2.0.)
+
+In order to replace placeholders, we need to know their list, but to get the best possible performance we do not maintain a single list of all placeholders since \LaTeX{} is quite slow when doing list manipulations. Therefore, we group them inside smaller groups (e.g.\ one group for |latex|, one group for |python| etc), and the user is free to import groups. By default, new placeholders are imported inside the |main| group, and this group will be used when doing placeholder replacements. Note that for most of the case, we define a star variant of functions like |\setPlaceholder*{__FOO__}{bar}| (or |set placeholder no import| for styles) in order to create a placeholder without importing it (but this is certainly not used a lot by end users unless they want to make them even faster).
+
+Note that basically all commands to create a placeholder have a command/environment where you add a star like |\setPlaceholder*{}| or a style where you add |no import| like |set placeholder no import| in order to create a placeholder that is not imported at all.
+
+\begin{pgfmanualentry}
+ \extractcommand\importPlaceholder\marg{name placeholder}\@@
+ \extractcommand\importPlaceholdersFromGroup\marg{name placeholder}\@@
+ \extractcommand\importAllPlaceholders\@@
+ \extractcommand\importPlaceholderFirst\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/import placeholder=\marg{name placeholder}\@nil
+ \extractkey/robExt/import placeholders from group=\marg{name group}\@nil
+ \extractkey/robExt/import all placeholders\@nil
+ \extractkey/robExt/import placeholder first=\marg{name placeholders}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Import placeholders, either individually, from a group of placeholders (exists either in style form or command), or from all registered groups (warning: you should avoid importing all placeholders if care too much about efficiency, as this can significantly slow down the replacement procedure). The |first| variant inserts the placeholder at the beginning of the import list, which can speed up compilation when this placeholder must be replaced first (but not so useful for basic usage).
+\begin{codeexample}[width=0pt,vbox]
+\robExtConfigure{
+ set placeholder no import={__name__}{Alice},
+ set placeholder no import={__name2__}{Bob},
+ print imported placeholders except default,
+ import placeholder={__name__},
+ print imported placeholders except default,
+ print imported placeholders,
+ import placeholders from group={latex},
+ print imported placeholders,
+}
+\end{codeexample}
+
+\begin{codeexample}[width=0pt,vbox]
+\printPlaceholder{First try: __ROBEXT_LATEX_TRIM_LENGTH__}
+\importAllPlaceholders
+\printPlaceholder{Second try: __ROBEXT_LATEX_TRIM_LENGTH__}
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\clearImportedPlaceholders\marg{name placeholder}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/clear imported placeholders\@nil
+ \makeatother%
+ \pgfmanualbody
+ Clear all imported placeholders (comma separated list of placeholders)
+\begin{codeexample}[width=0pt,vbox]
+\robExtConfigure{
+ set placeholder={__name__}{Alice},
+ print imported placeholders except default,
+ clear imported placeholders,
+ print imported placeholders except default,
+}
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\removeImportedPlaceholder\marg{name placeholder}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/remove imported placeholders\@nil
+ \makeatother%
+ \pgfmanualbody
+ Comma separated list of placeholders to remove from the list of imported placeholders.
+\begin{codeexample}[width=0pt,vbox]
+\robExtConfigure{
+ set placeholder={__name__}{Alice},
+ set placeholder={__name2__}{Alice},
+ print imported placeholders except default,
+ remove imported placeholders={__name__,__name2__},
+ print imported placeholders except default,
+}
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\printAllRegisteredGroups\@@
+ \extractcommand\printAllRegisteredGroupsAndPlaceholders\opt{*}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/print all registered groups\@nil
+ \extractkey/robExt/print all registered groups and placeholders\@nil
+ \extractkey/robExt/show all registered groups\@nil
+ \extractkey/robExt/show all registered groups and placeholders\@nil
+ \makeatother%
+ \pgfmanualbody
+ Print (or shows in the console for the alternative versions) all registered groups of placeholders (possibly with the placeholders they contain), mostly for debugging purpose, with the star prints also the content of the inner placeholders.
+\begin{codeexample}[width=0pt,vbox]
+\printAllRegisteredGroups
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\printGroupPlaceholders\opt{*}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/print group placeholders=\marg{name group}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Print all placeholders (star = with content) of a given group.
+\begin{codeexample}[width=0pt,vbox]
+\printGroupPlaceholders*{bash}
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\printAllRegisteredGroupsAndPlaceholders\opt{*}\@@
+ \pgfmanualbody
+ Print all registered groups of placeholders with their inner content, mostly for debugging purpose, with the star prints only the content of the inner placeholders.
+\begin{codeexample}[width=0pt,vbox]
+\printAllRegisteredGroupsAndPlaceholders
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\newGroupPlaceholders\marg{name group}\@@
+ \extractcommand\addPlaceholderToGroup\marg{name group}\marg{list,of,placeholders}\@@
+ \extractcommand\addPlaceholdersToGroup\marg{name group}\marg{list,of,placeholders}\@@
+ \extractcommand\removePlaceholderFromGroup\marg{name group}\marg{list,of,placeholders}\@@
+ \extractcommand\removePlaceholdersFromGroup\marg{name group}\marg{list,of,placeholders}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/new group placeholders=\marg{name group}\@nil
+ \extractkey/robExt/add placeholder to group=\marg{name group}\marg{name placeholder}\@nil
+ \extractkey/robExt/add placeholders to group=\marg{name group}\marg{list,of,placeholders}\@nil
+ \extractkey/robExt/add placeholders to group=\marg{name group}\marg{list,of,placeholders}\@nil
+ \extractkey/robExt/remove placeholders from group=\marg{name group}\marg{list,of,placeholders}\@nil
+ \extractkey/robExt/remove placeholder from group=\marg{name group}\marg{list,of,placeholders}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Create a new group and add placeholders to it (you can put multiple placeholders separated by commas).
+\begin{codeAndResult}
+\robExtConfigure{
+ new group placeholders={my dummy group},
+ set placeholder no import={__name__}{Alice},
+ add placeholders to group={my dummy group}{__name__},
+}
+\printGroupPlaceholders{my dummy group}
+\removePlaceholdersFromGroup{my dummy group}{__name__}
+\printGroupPlaceholders{my dummy group}
+\end{codeAndResult}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\clearGroupPlaceholders\marg{name group}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ % \extractkey/robExt/new group placeholders=\marg{name group}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Remove all elements in a group.
+\begin{codeexample}[vbox]
+\robExtConfigure{
+ new group placeholders={my dummy group},
+ set placeholder no import={__name__}{Alice},
+ add placeholders to group={my dummy group}{__name__},
+}
+\clearGroupPlaceholders{my dummy group}
+\printGroupPlaceholders{my dummy group}
+\end{codeexample}
+\end{pgfmanualentry}
+
+
+\begin{pgfmanualentry}
+ \extractcommand\copyGroupPlaceholders\marg{name group}\marg{name group to copy}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/copy group placeholders=\marg{name group}\marg{name group to copy}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Remove all elements in a group.
+\begin{codeexample}[vbox]
+\robExtConfigure{
+ new group placeholders={my dummy group},
+ set placeholder no import={__name__}{Alice},
+ add placeholders to group={my dummy group}{__name__},
+}
+\copyGroupPlaceholders{my copy}{my dummy group}
+\printGroupPlaceholders{my copy}
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\appendGroupPlaceholders\marg{name group}\marg{name group to append}\@@
+ \extractcommand\appendBeforeGroupPlaceholders\marg{name group}\marg{name group to append}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/append group placeholders=\marg{name group}\marg{name group to copy}\@nil
+ \extractkey/robExt/append before group placeholders=\marg{name group}\marg{name group to copy}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Append a group to another group (after or before).
+\begin{codeexample}[vbox]
+\robExtConfigure{
+ new group placeholders={my dummy group},
+ set placeholder no import={__name__}{Alice},
+ add placeholders to group={my dummy group}{__name__},
+ new group placeholders={my dummy group2},
+ set placeholder no import={__name2__}{Bob},
+ add placeholders to group={my dummy group2}{__name2__},
+ append group placeholders={my dummy group}{my dummy group2},
+}
+\printGroupPlaceholders{my dummy group}
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\importPlaceholdersFromGroup\marg{name group}\@@
+ \extractcommand\importAllPlaceholders\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/import placeholders from group=\marg{name group}\@nil
+ \extractkey/robExt/import all placeholders\@nil
+ \makeatother%
+ \pgfmanualbody
+ Import a group/all registered groups (note that this is equivalent to appending to the group called |main|). Note that for the later, you should be sure that the group is ``registered'', which is the case if you created it via |new group placeholders|.
+\begin{codeexample}[vbox]
+\robExtConfigure{
+ new group placeholders={my dummy group},
+ set placeholder no import={__name__}{Alice},
+ add placeholder to group={my dummy group}{__name__},
+ import all placeholders,
+}
+\printImportedPlaceholdersExceptDefaults
\end{codeexample}
- It is useful for instance if you want to use a different value for |__ROBEXT_MAIN_CONTENT__|: first copy |__ROBEXT_MAIN_CONTENT__| to another placeholder, say |__NEW_MAIN_CONTENT__|, and then set |__ROBEXT_MAIN_CONTENT__| to point to an arbitrary template that may load |__NEW_MAIN_CONTENT__|.
\end{pgfmanualentry}
@@ -1161,7 +1885,7 @@ As a sanity check, this file contains
\extractcommand\cacheMe\opt{\oarg{preset style}}\marg{content to cache}\@@
\extractenvironement{CacheMe}\marg{preset style}\@@
\pgfmanualbody
- This command (and its environment alias) is the main entry point if you want to cache the result of a file. The preset style is a pgfkeys-based style that is used to configure the template that is used, the compilation command, and more. You can either inline the style, or use some presets that configure the style automatically. After evaluating the style, the placeholders |__ROBEXT_TEMPLATE__| (containing the content of the file) and |__ROBEXT_COMPILATION_COMMAND__| (containing the compilation command run in the cache folder, that can use other placeholders internally like |__ROBEXT_SOURCE_FILE__| to get the path to the source file) should be set. Note that we provide some basic styles that allow settings these placeholders easily. See \cref{sec:placeholders} for a list of existing placeholders and presets. The placeholder |__ROBEXT_MAIN_CONTENT__| will automatically be set by this command (or environment) so that it equals the content of the second argument (or the body of the environment). This style can also configure the command to use to include the file and more. By default it will insert the compiled PDF, making sure that the depth is respected (internally, we read the depth from an aux file created by our \LaTeX{} preset), but you can easily change it to anything you like.
+ This command (and its environment alias) is the main entry point if you want to cache the result of a file. The preset style is a pgfkeys-based style that is used to configure the template that is used, the compilation command, and more. You can either inline the style, or use some presets that configure the style automatically. After evaluating the style, the placeholders |__ROBEXT_TEMPLATE__| (containing the content of the file) and |__ROBEXT_COMPILATION_COMMAND__| (containing the compilation command run in the cache folder, that can use other placeholders internally like |__ROBEXT_SOURCE_FILE__| to get the path to the source file) should be set. Note that we provide some basic styles that allow settings these placeholders easily. See \cref{sec:placeholders} for a list of existing placeholders and presets. The placeholder |__ROBEXT_MAIN_CONTENT_ORIG__| will automatically be set by this command (or environment) so that it equals the content of the second argument (or the body of the environment). By default, |__ROBEXT_MAIN_CONTENT__| will point to |__ROBEXT_MAIN_CONTENT_ORIG__|, possibly wrapping it inside an environment like |\begin{tikzpicture}| (most of the time, you want to modify and display |__ROBEXT_MAIN_CONTENT__| rather than the |_ORIG_| to easily recover the input of the user). This style can also configure the command to use to include the file and more. By default it will insert the compiled PDF, making sure that the depth is respected (internally, we read the depth from an aux file created by our \LaTeX{} preset), but you can easily change it to anything you like.
For an educational purpose, we write here an example that does not exploit any preset. In practice, we recommend however to use our presets, or to define new presets based on our presets (see below for examples).
\begin{codeexample}[width=0pt,vbox]
@@ -1183,19 +1907,30 @@ This content is cached $\delta$.
\begin{pgfmanualentry}
\extractcommand\robExtConfigure\marg{preset style}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/new preset=\marg{name preset}\marg{preset options}\@nil
+ \extractkey/robExt/add to preset=\marg{name preset}\marg{preset options}\@nil
+ \makeatother%
\pgfmanualbody
- You can then create your own style (or preset) in |\robExtConfigure| (that is basically an alias for |\pgfkeys{/robExt/.cd,#1}|) containing your template, add your own placeholders and commands to configure them etc.
+ You can then create your own style (or preset) in |\robExtConfigure| (that is basically an alias for |\pgfkeys{/robExt/.cd,#1}|) containing your template, add your own placeholders and commands to configure them etc. We provide two helper functions since v2.0:\\
+ |new preset={your preset}{your configuration}|\\
+ and\\
+ |add to preset={your preset}{your configuration}|\\
+ in order to create/modify the presets. You can also use |my preset/.style| or\\
+ |my preset/.append style|\\
+ to configure them instead, but in that case make sure to double the number of hashes like in |\def\mymacro##1{hello ##1}|, as the |#1| in |\def\mymacro#1{hello #1}.| would be understood as the (non-existent) argument of |my preset|.
\begin{codeexample}[width=0pt,vbox]
%% Define your presets once:
\robExtConfigure{%
- my latex preset/.style={
+ new preset={my latex preset}{
%% Create a default value for my new placeholders:
set placeholder={__MY_COLOR__}{red},
set placeholder={__MY_ANGLE__}{45},
% We can also create custom commands to "hide" the notion of placeholder
set my angle/.style={
- set placeholder={__MY_ANGLE__}{##1}
+ set placeholder={__MY_ANGLE__}{#1}
},
set template={
\documentclass{standalone}
@@ -1247,17 +1982,17 @@ plt.savefig("__ROBEXT_OUTPUT_PDF__")
% Create a new preset called matplotlib
\robExtConfigure{
- matplotlib figure/.style={
+ new preset={matplotlib figure}{
set template={__MY_MATPLOTLIB_TEMPLATE__},
set compilation command={python "__ROBEXT_SOURCE_FILE__"},
set caption/.style={
- set placeholder={__FIG_CAPTION__}{##1}
+ set placeholder={__FIG_CAPTION__}{#1}
},
set label/.style={
- set placeholder={__FIG_LABEL__}{##1}
+ set placeholder={__FIG_LABEL__}{#1}
},
set includegraphics options/.style={
- set placeholder={__INCLUDEGRAPHICS_OPTIONS__}{##1}
+ set placeholder={__INCLUDEGRAPHICS_OPTIONS__}{#1}
},
set caption={},
set label={},
@@ -1297,17 +2032,17 @@ plt.savefig("__ROBEXT_OUTPUT_PDF__")
% Create a new preset called matplotlib
\robExtConfigure{
- matplotlib figure/.style={
+ new preset={matplotlib figure}{
set template={__MY_MATPLOTLIB_TEMPLATE__},
set compilation command={python "__ROBEXT_SOURCE_FILE__"},
set caption/.style={
- set placeholder={__FIG_CAPTION__}{##1}
+ set placeholder={__FIG_CAPTION__}{#1}
},
set label/.style={
- set placeholder={__FIG_LABEL__}{##1}
+ set placeholder={__FIG_LABEL__}{#1}
},
set includegraphics options/.style={
- set placeholder={__INCLUDEGRAPHICS_OPTIONS__}{##1}
+ set placeholder={__INCLUDEGRAPHICS_OPTIONS__}{#1}
},
set caption={},
set label={},
@@ -1348,11 +2083,11 @@ plt.savefig("__ROBEXT_OUTPUT_PDF__")
% Create a new preset called matplotlib
\robExtConfigure{
- matplotlib/.style={
+ new preset={matplotlib}{
set template={__MY_MATPLOTLIB_TEMPLATE__},
set compilation command={python "__ROBEXT_SOURCE_FILE__"},
set includegraphics options/.style={
- set placeholder={__INCLUDEGRAPHICS_OPTIONS__}{##1}
+ set placeholder={__INCLUDEGRAPHICS_OPTIONS__}{#1}
},
set includegraphics options={width=1cm},
custom include command={%
@@ -1395,6 +2130,15 @@ plt.ylabel('Number of futurestud.io Tutorials')
Style that alias to |set placeholder={__ROBEXT_TEMPLATE__}{#1}|, in order to define the placeholder that will hold the template of the final file.
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/set template=\marg{content template}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Style that alias to |set placeholder={__ROBEXT_TEMPLATE__}{#1}|, in order to define the placeholder that will hold the template of the final file.
+\end{pgfmanualentry}
+
\subsubsection{Options to configure the compilation command}\label{sec:configureCompilationCommand}
\begin{pgfmanualentry}
@@ -1438,6 +2182,17 @@ plt.ylabel('Number of futurestud.io Tutorials')
two arguments, where the first argument is the key, but this time the second argument is the path of |filename| relative to the cache folder (useful since scripts run from this folder). Moreover, it automatically ensures that when |filename| changes, the file gets recompiled. Note that contrary to some other commands, this does not copy the file in the cache, which is practical notably for large files like videos.
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/force compilation\@nil
+ \extractkey/robExt/do not force compilation\@nil
+ \makeatother%
+ \pgfmanualbody
+ By default, we compile cached documents only if |-shell-escape| is enabled. However, if the user allowed |pdflatex| (needed to compile latex documents), |cd| (not needed when using |no cache folder|), and |mkdir| (not needed when using |no cache folder| or if the cache folder that defaults to |robustExternalize| is already created) to run in restricted mode (so without enabling |-shell-escape|), then there is no need for |-shell-escape|. In that case, set |force compilation| and this library will compile even if |-shell-escape| is disabled.
+\end{pgfmanualentry}
+
+
\subsubsection{Options to configure the inclusion command}
The inclusion command is the command that is run to include the cached file back in the pdf (e.g. based on |\includegraphics|). We describe now how to configure this command.
@@ -1477,6 +2232,8 @@ The inclusion command is the command that is run to include the cached file back
\def\extrakeytext{style, }
\extractkey/robExt/enable manual mode\@nil
\extractkey/robExt/disable manual mode\@nil
+ \extractkey/robExt/enable fallback to manual mode\@nil
+ \extractkey/robExt/disable fallback to manual mode\@nil
\makeatother%
\pgfmanualbody
If you do or do not want to ask latex to run the compilation commands itself (for instance for security
@@ -1488,12 +2245,13 @@ The inclusion command is the command that is run to include the cached file back
The next picture must be manually compiled %
(see JOBNAME-robExt-compile-missing-figures.sh):\\ %
- \begin{tikzpictureC}[baseline=(A.base)][]
+ \begin{tikzpictureC}[baseline=(A.base)]
\node[fill=red, rounded corners](A){I must be manually compiled.};
\node[fill=red, rounded corners, opacity=.3,overlay] at (A.north east){I am an overlay text};
\end{tikzpictureC}
\end{codeexample}
-
+ The main difference between |manual mode| and |fallback to manual mode| is that |fallback to manual mode| will try to compile the file if |-shell-escape| is enabled, while |manual mode| will never run any command, even if |-shell-escape| is enabled. Note that |enable fallback to manual mode| is available starting from v2.0.
+
See \cref{sec:operationsCache} for more details.
\end{pgfmanualentry}
@@ -1523,31 +2281,47 @@ If needed, you can configure the cache:
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/set subfolder and way back=\marg{cache folder}\marg{path to project from cache}\@nil
+ \extractkey/robExt/set cache folder and way back=\marg{cache folder}\marg{path to project from cache}\@nil
\makeatother%
\pgfmanualbody
By default, the cache is located in |robustExternalize/|, using:\\
- |set subfolder and way back={robustExternalize/}{../},|\\
- You can customize it the way you want, just be make sure that going to the second arguments after going to the first argument leads you back to the original position.
+ |set cache folder and way back={robustExternalize/}{../},|\\
+ You can customize it the way you want, just be make sure that going to the second arguments after going to the first argument leads you back to the original position, and make sure to terminate the path with a |/| so that |__ROBEXT_WAY_BACK__common_inputs.tex| gives the path of the file |common_inputs.tex| in the root folder (do not write |__ROBEXT_WAY_BACK__/common_inputs.tex| as this would expand to the absolute path |/common_inputs.tex| if you disable the cache folder). Note that both:\\
+ |set cache folder and way back|\\
+ and\\
+ |set subfolder and way back|\\
+ are alias, but the first one was introduced in v2.0 as it is clearer, the second one being kept for backward compatibility.
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/no cache folder\@nil
+ \makeatother%
+ \pgfmanualbody
+ Do not put the cache in a separate subfolder.
+\end{pgfmanualentry}
+
+
\newpage
\subsubsection{Customize or disable externalization}\label{sec:disableExternalization}
-You might want (sometimes or always) to disable externalization, for instance to use |remember picture| \tikz[remember picture,baseline=(pointtome.base)] \node[rounded corners, fill=orange](pointtome){Point to me if you can};, even if you used |\robExtExternalizeAllTikzpictures|:
+You might want (sometimes or always) to disable externalization, for instance to use |remember picture| \tikz[remember picture,baseline=(pointtome.base)] \node[rounded corners, fill=orange](pointtome){Point to me if you can};, even if you used |\cacheTikz|:
\begin{pgfmanualentry}
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/disable externalization\@nil
+ \extractkey/robExt/disable externalization now\@nil
\extractkey/robExt/enable externalization\@nil
\makeatother%
\pgfmanualbody
Enable or disable externalization.
\begin{codeexample}[width=0pt,vbox]
% In theory all pictures should be externalized (so remember picture should fail)
- \robExtExternalizeAllTikzpictures
+ \cacheTikz
% But we can disable it temporarily
- \begin{tikzpicture}[remember picture][disable externalization]
+ \begin{tikzpicture}<disable externalization>[remember picture]
\node[rounded corners, fill=red](A){This figure is not externalized.
This way, it can use remember picture.};
\draw[->,overlay] (A) to[bend right] (pointtome);
@@ -1570,6 +2344,16 @@ You might want (sometimes or always) to disable externalization, for instance to
\end{tikzpicture}
}
\end{codeexample}
+ |disable externalization now| additionally redefines all automatically cached commands and environments to their default value right now (|disable externalization| would only do so when running the |command if no externalization| is run, which should be preferred if possible). This is mostly useful when an automatically cached command cannot be parsed (e.g.\ you specified the signature |O{}m| but in fact the command expects a more complicated parsing algorithm. For instance, in |tikz| we can omit the brackets, and it might confuse the system if we defined it as:
+ \begin{codeexample}[width=0pt,vbox]
+ %% Not the recommended way to proceed, but this is for the example
+ \cacheCommand{tikz}[O{}m]{tikz}
+ {
+ % Needed, or the parser would be confused by the next command
+ \robExtConfigure{disable externalization now}
+ \tikz\node[fill=green]{The short version of tikz can be confusing.};
+ }
+ \end{codeexample}
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -1584,6 +2368,7 @@ command if no externalization/.code={%
\robExtDisableTikzpictureOverwrite\evalPlaceholder{__ROBEXT_MAIN_CONTENT__}%
}
\end{verbatim}
+Unless you know what you are doing, you should include |\robExtDisableTikzpictureOverwrite| as it is often necessary to avoid infinite recursion when externalization is disabled and the original command has been replaced with a cached version (for instance done by |\cacheTikz|). Note that if you write your own style, try to modify |__ROBEXT_MAIN_CONTENT__| so that it can be included as-it in a document: this way you do not need to change this command.
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -1612,7 +2397,7 @@ You can also disable the externalization on all elements that use a common prese
\begin{codeAndResult}
\robExtConfigure{
% bash code will not be compiled (useful on windows for instance)
- bash/.append style={
+ add to preset={bash}{
disable externalization
},
}
@@ -1652,7 +2437,7 @@ In order to enforce reproducibility, you should tell what are the files that you
\begin{codeexample}[width=0pt,vbox]
\begin{CacheMe}{latex,
add dependencies={common_inputs.tex},
- add to preamble={\input{__ROBEXT_WAY_BACK__/common_inputs.tex}}}
+ add to preamble={\input{__ROBEXT_WAY_BACK__common_inputs.tex}}}
The answer is \myValueDefinedInCommonInputs.
\end{CacheMe}
\end{codeexample}
@@ -1660,7 +2445,7 @@ Note that the placeholder |__ROBEXT_WAY_BACK__| contains the path from the cache
\end{pgfmanualentry}
-\subsubsection{Pass compiled file to another template}
+\subsubsection{Pass compiled file to another template}\label{sec:passOutputToOtherTemplate}
It can sometimes be handy to use the result of a previous cached file to cache another file, or to do anything else (e.g.\ it can also be practical to debug an issue). |name output| can be used to do that
\begin{pgfmanualentry}
@@ -1672,7 +2457,7 @@ It can sometimes be handy to use the result of a previous cached file to cache a
|name output=foo| will create two global macros |\foo| and |\fooInCache|: |\foo| expands to the prefix of the files created in the template like |robExt-somehash|, and |\fooInCache| also adds the cache folder like |robustExternalize/robExt-somehash|. You can then use |set placeholder eval| to send it to another cached file. It is then your role to add the extension, usually |.tex| to get the source (even if the source is a python file), |.pdf| to get the pdf, |-out.tex| to get the file that is loaded before the import, |-out.txt| if you wanted to make it compatible with |verbatim output| (this list is not exhaustive as each script might decide to create a different output file). Here is a demo:
\begin{codeexample}[width=0cm,vbox]
-\begin{CacheMe}{tikz, do not add margins, name output=mycode}[baseline=(A.base)]
+\begin{CacheMe}{tikzpicture, do not add margins, name output=mycode}[baseline=(A.base)]
\node[draw,rounded corners,fill=pink!60](A){Hello World!};
\end{CacheMe}\\[3mm]
@@ -1682,7 +2467,7 @@ It this can be helpful for instance to debug, as you can inspect the source:
\verbatiminput{\mycodeInCache.tex}
but it is also practical to define a template based on the previously cached files:\\
-\begin{CacheMe}{tikz, set placeholder eval={__previous__}{\mycode.pdf}}
+\begin{CacheMe}{tikzpicture, set placeholder eval={__previous__}{\mycode.pdf}}
\node[rounded corners, fill=green!50]{A cached file can use result from another cached file:
\includegraphics[width=2cm]{__previous__}\includegraphics[width=2cm]{__previous__}};
\end{CacheMe}
@@ -1692,6 +2477,56 @@ Note that if you do not want to display the first cached file, you can use |do n
\end{pgfmanualentry}
+\subsubsection{Compile even faster}\label{sec:compileFaster}
+
+Long story short: you can compile even faster (at least 1.5x in our tests, but we expect this to be more visible on larger tests due to the loading time of the preamble of the main document that takes most of the time of the compilation) by compiling presets, but beware that you will not be able to modify the placeholders except |add to preamble| with the default compiler we provide:
+
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/new compiled preset=\marg{preset options to compile}\marg{runtime options}\@nil
+ \extractkey/robExt/compile latex template\@nil
+ \makeatother%
+ \pgfmanualbody
+ Compile a preset by creating a new placeholders that removes all placeholders except |__ROBEXT_MAIN_CONTENT__|, |__ROBEXT_MAIN_CONTENT_ORIG__| and |__ROBEXT_LATEX_PREAMBLE__|. |preset options to compile| should be sure that the template, compilation command and include command placeholders contain the final version: this can be easily done for latex presets by adding |compile latex template| at the end of |preset options to compile|:.
+\begin{codeexample}[vbox]
+ % We create a latex-based preset and compile it
+\robExtConfigure{
+ new preset={templateZX}{
+ latex,
+ add to preamble={
+ \usepackage{tikz}
+ \usepackage{tikz-cd}
+ \usepackage{zx-calculus}
+ },
+ %% possibly add some dependencies
+ },
+ % We compile it into a new preset
+ new compiled preset={compiled ZX}{templateZX, compile latex template}{},
+}
+
+% we use that preset automatically for ZX environments
+\cacheEnvironment{ZX}{compiled ZX}
+\cacheCommand{zx}{compiled ZX}
+
+% Usage: (you can't use placeholders except for the preamble, trade-off of the compiled template)
+\begin{ZX}<add to preamble={\def\sayHey#1{Hey #1!}}>
+ \zxX{\sayHey{Bob}}
+\end{ZX}
+\end{codeexample}
+\end{pgfmanualentry}
+
+
+Explanations: in v2.0, we made substantial improvements in order to improve significantly the compilation time (our benchmark went from 20s (v1.0) to only 5.77s (v2.0)), but you might want to make this even faster: with a compiled preset, you can improve it further, experimentation showed an additional improvement factor of 1.4x (final compilation time was 4s in our tests, reminder: without the library it would take 1mn25s). The main bottleneck in term of time is the expansion of the placeholders (that allows great flexibility, but can add a significant time). At a high level, we keep track in a list of all declared placeholders, and loop over them to replace each of them until the string is left unmodified by a full turn. This is simple to implement, does not need to assume any shape for the placeholder\dots{} but not extremely efficient in \LaTeX{} where string and list manipulations are costly.
+
+We can play on multiple parameters to speed up the process:
+\begin{itemize}
+\item Disable completely the placeholders and only replace a small amount of fixed placeholders in a fixed order and stop expanding the placeholder. This is what we do by default when we compile a preset: it is the quickest solution, but you cannot use arbitrary placeholders.
+\item Start the expansion using a fixed (preset-dependent) list of placeholders, check if some templates are still present (assuming that templates must contain at least two consecutive underscores |__|), if not stop, otherwise go to the normal (less efficient) placeholder replacement. It is what we do for instance in the latex preset, and gives a great balance between efficiency and flexibility. Details can be found in \cref{sec:advancedOperations}.
+\item Stop iterating over all placeholders, only choose the one meaningful (why would I care about python placeholders in latex?). For this, we introduce an import system, where you can create placeholders that are not added to the ``global'' list of placeholders, and import them where you want. In practice, you should not really need to use it unless you do more advanced stuff as we already take care of setting it properly, but details are in \cref{sec:importSystem}.
+\end{itemize}
+Another option could be to rewrite the code to search directly the list of placeholders in the string, but it is certainly not trivial to do in latex, would require even more constraints on the shape of placeholders, and would certainly still no more efficient than the compiled stuff. But anyway the already implemented solutions already give fairly good performances.
\subsection{Default presets}\label{sec:presets}
@@ -1739,8 +2574,28 @@ with open("__ROBEXT_OUTPUT_PREFIX__-out.txt", "w") as f:
\end{codeAndResult}
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/debug\@nil
+ \extractkey/robExt/print command and source\@nil
+ \makeatother%
+ \pgfmanualbody
+ (new in v2.0) These two (alias) commands allow you to print the compilation command, the dependency file (useful to be sure you tracked all dependencies), and the source file:
+\begin{codeexample}[width=0pt,vbox]
+\begin{CacheMe}{latex,
+ add dependencies={common_inputs.tex},
+ add to preamble={\input{__ROBEXT_WAY_BACK__common_inputs.tex}},
+ debug
+ }
+ The answer is \myValueDefinedInCommonInputs.
+\end{CacheMe}
+\end{codeexample}
-\subsubsection{\LaTeX{}}
+\end{pgfmanualentry}
+
+
+\subsubsection{\LaTeX{} and \tikzname{}}
The |latex| preset is used to cache any \LaTeX{} content, like tikz pictures. Note that as of today, it supports overlay content out of the box (if the overlay is more than 30cm long, you might want to customize a placeholder), but not images that need to use |remember picture|.
@@ -1750,7 +2605,7 @@ The |latex| preset is used to cache any \LaTeX{} content, like tikz pictures. No
\extractkey/robExt/latex\@nil
\makeatother%
\pgfmanualbody
- This style sets the template |__ROBEXT_LATEX__| and the compilation command:\\ |__ROBEXT_COMPILATION_COMMAND_LATEX__|\\
+ This style sets the template |__ROBEXT_LATEX__| and the compilation command:\\ |__ROBEXT_LATEX_COMPILATION_COMMAND__|\\
(cf \cref{sec:placeholders} for details), and adds a number of styles described below, to easily configure the most common options. You can use it as follows:
\begin{codeexample}[width=0pt,vbox]
The next picture is cached %
@@ -1797,7 +2652,7 @@ The next options can be used after calling the |latex| style:
\extractkey/robExt/latex/set documentclass=\marg{documentclass}\@nil
\makeatother%
\pgfmanualbody
- Set the documentclass of the document (defaults to |standalone|). Internally, it sets the placeholder |__ROBEXT_DOCUMENT_CLASS__|.
+ Set the documentclass of the document (defaults to |standalone|). Internally, it sets the placeholder |__ROBEXT_LATEX_DOCUMENT_CLASS__|.
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -1805,9 +2660,13 @@ The next options can be used after calling the |latex| style:
\def\extrakeytext{style, }
\extractkey/robExt/latex/set preamble=\marg{code of preamble}\@nil
\extractkey/robExt/latex/add to preamble=\marg{code of preamble}\@nil
+ \extractkey/robExt/latex/set preamble hyperref=\marg{code of preamble}\@nil
+ \extractkey/robExt/latex/add to preamble hyperref=\marg{code of preamble}\@nil
+ \extractkey/robExt/latex/set preamble after hyperref=\marg{code of preamble}\@nil
+ \extractkey/robExt/latex/add to preamble after hyperref=\marg{code of preamble}\@nil
\makeatother%
\pgfmanualbody
- Set/add element to the preamble (defaults to |standalone|). Internally, it sets the placeholder |__ROBEXT_DOCUMENT_CLASS__|.
+ Set/add element to the preamble (defaults to |standalone|). Internally, it sets the placeholder |__ROBEXT_LATEX_PREAMBLE__|. The variations |hyperref| and |after hyperref| are used to put stuff after the preambule, as |hyperref| typically needs to be loaded last (or nearly): packages that must be loaded after |hyperref| like |cref| can be added via |add to preamble after hyperref|.
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -1817,9 +2676,32 @@ The next options can be used after calling the |latex| style:
\makeatother%
\pgfmanualbody
By default, the main content is wrapped into a box in order to measure its depth to properly set the baseline. If you do not want to do this wrapping, you can set this option. Internally, it is a shortcut for:\\
- |set placeholder={__ROBEXT_MAIN_CONTENT_WRAPPED__}{__ROBEXT_MAIN_CONTENT__}|
+ |set placeholder={__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__}{__ROBEXT_MAIN_CONTENT__}|
+ \textbf{IMPORTANT}: note that it means that you might need to adapt your code to take into account the fact that they are inside a box (I don't know of any other solution to compute the depth, but it does not mean that there is none).
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/latex/in command\@nil
+ \makeatother%
+ \pgfmanualbody
+ Sets |__ROBEXT_MAIN_CONTENT| to point to |__ROBEXT_MAIN_CONTENT_ORIG__| to remove any wrapping of the user input, for instance made by tikzpicture.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/tikz\@nil
+ \extractkey/robExt/tikzpicture\@nil
+ \makeatother%
+ \pgfmanualbody
+ |tikz| loads |latex| and then adds |tikz| to the preamble. |tikzpicture| first load |tikz| and wraps the main content within |\begin{tikzpicture}| and |\end{tikzpicture}| using:\\
+ |set placeholder={__ROBEXT_MAIN_CONTENT__}{\begin{tikzpicture}__ROBEXT_MAIN_CONTENT_ORIG__\end{tikzpicture}}|\\
+ so that the user does not need to type it. See for instance the introduction for examples of use.
\end{pgfmanualentry}
+
\subsubsection{Python}
We provide support for python:
@@ -1908,10 +2790,6 @@ You can set |__ROBEXT_PYTHON_TCOLORBOX_PROPS__| the options of the tcolorbox,\\
\end{verbatim}
\end{pgfmanualentry}
-
-
-
-
\subsubsection{Bash}
We provide a basic bash template, that sets:
@@ -1959,16 +2837,22 @@ This file contains:
\verbatiminput{\robExtPathToInput}
\end{codeAndResult}
+\subsubsection{Custom languages}
+
+To add support to new languages, see \cref{sec:otherLanguages} for an example.
+
+
\subsection{List of special placeholders and presets}\label{sec:placeholders}
-This library defines a number of pre-existing placeholders, or placeholders playing a special role. We list some of them in this section. All placeholders created by this library start with |__ROBEXT_|. Note that you can list all predefined placeholders (at least those globally defined) using |\printAllPlaceholdersExceptDefaults| (note that some other placeholders might be created directly in the style set right before the command, and may not appear in this list if you call it before setting the style).
+This library defines a number of pre-existing placeholders, or placeholders playing a special role. We list some of them in this section. All placeholders created by this library start with |__ROBEXT_|. Note that you can list all predefined placeholders (at least those globally defined) using |\printImportedPlaceholdersExceptDefaults| (note that some other placeholders might be created directly in the style set right before the command, and may not appear in this list if you call it before setting the style).
\subsubsection{Generic placeholders}
We define two special placeholders that should be defined by the user (possibly indirectly, using presets offered by this library):
\begin{itemize}
\item |__ROBEXT_TEMPLATE__| is a placeholder that should contain the code of the file to compile.
-\item |__ROBEXT_MAIN_CONTENT__|: is a placeholder that might be used inside |__ROBEXT_TEMPLATE__| and that contains the content that the user is expected to type inside the document. For instance, this might be a tikz picture, a python function without the import etc. This will be automatically set by |CacheMe|, |CacheMeCode| etc, and some styles might add stuff to it (for instance the |tikz| preset adds the |\begin{tikzpicture}| around the user code automatically: this way we do not need to edit the command to disable externalization).
+\item |__ROBEXT_MAIN_CONTENT_ORIG__| is a placeholder containing the text typed by the user, automatically set by |CacheMe|, |CacheMeCode| etc. You rarely need to deal with this placeholder directly since |__ROBEXT_MAIN_CONTENT__| will typically point to it and add some necessary wrapping.
+\item |__ROBEXT_MAIN_CONTENT__| is a placeholder that might be used inside |__ROBEXT_TEMPLATE__|, that points by default to |__ROBEXT_MAIN_CONTENT_ORIG__| and that contains the content that should be typed inside the document. For instance, this might be a tikz picture, a python function without the import etc. Note that it is often used to wrap the text of the user |__ROBEXT_MAIN_CONTENT_ORIG__|: for instance, the |tikzpicture| preset adds the |\begin{tikzpicture}| around the user code automatically: this way we do not need to edit the command to disable externalization.
\item |__ROBEXT_COMPILATION_COMMAND__| contains the compilation command to run to compile the file (assuming we are in the cache folder).
\end{itemize}
@@ -1992,14 +2876,14 @@ Some placeholders are reserved only when dealing with \LaTeX{} code:
\begin{itemize}
\item |__ROBEXT_LATEX__| is the main entrypoint, containing all the latex template. It internally calls other placeholders listed below.
\item |__ROBEXT_LATEX_OPTIONS__|: contains the options to compile the document, like |a4paper|. Empty by default.
-\item |__ROBEXT_DOCUMENT_CLASS__|: contains the class of the document. Defaults to |standalone|.
-\item |__ROBEXT_PREAMBLE__|: contains the preamble. Is empty by default.
-\item |__ROBEXT_MAIN_CONTENT_WRAPPED__|: content inside the |document| environment. It will wrap the actual content typed by the user |__ROBEXT_MAIN_CONTENT__| around a box to compute its depth. If you do not want this behavior, you can set |__ROBEXT_MAIN_CONTENT_WRAPPED__| to be equal to |__ROBEXT_MAIN_CONTENT__|. It calls internally |__ROBEXT_CREATE_OUT_FILE__| and |__ROBEXT_WRITE_DEPTH_TO_OUT_FILE__| to do this computation.
-\item |__ROBEXT_CREATE_OUT_FILE__| creates a new file called |\jobname-out.tex| and open it in the handle called |\writeRobExt|
-\item |__ROBEXT_WRITE_DEPTH_TO_OUT_FILE__| writes the height, depth and width of the box |\boxRobExt| into the filed opened in |\writeRobExt|.
-\item |__ROBEXT_COMPILATION_COMMAND_LATEX__| is the command used to compile a \LaTeX{} document. It uses internally other placeholders:
+\item |__ROBEXT_LATEX_DOCUMENT_CLASS__|: contains the class of the document. Defaults to |standalone|.
+\item |__ROBEXT_LATEX_PREAMBLE__|: contains the preamble. Is empty by default.
+\item |__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__|: content inside the |document| environment. It will wrap the actual content typed by the user |__ROBEXT_MAIN_CONTENT__| around a box to compute its depth. If you do not want this behavior, you can set |__ROBEXT_LATEX_MAIN_CONTENT_WRAPPED__| to be equal to |__ROBEXT_MAIN_CONTENT__|. It calls internally |__ROBEXT_LATEX_CREATE_OUT_FILE__| and |__ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__| to do this computation.
+\item |__ROBEXT_LATEX_CREATE_OUT_FILE__| creates a new file called |\jobname-out.tex| and open it in the handle called |\writeRobExt|
+\item |__ROBEXT_LATEX_WRITE_DEPTH_TO_OUT_FILE__| writes the height, depth and width of the box |\boxRobExt| into the filed opened in |\writeRobExt|.
+\item |__ROBEXT_LATEX_COMPILATION_COMMAND__| is the command used to compile a \LaTeX{} document. It uses internally other placeholders:
\item |__ROBEXT_LATEX_ENGINE__| is the engine used to compile the document (defaults to |pdflatex|)
-\item |__ROBEXT_COMPILATION_COMMAND_OPTIONS__| contains the options used to compile the document (defaults to |-shell-escape -halt-on-error|)
+\item |__ROBEXT_LATEX_COMPILATION_COMMAND_OPTIONS__| contains the options used to compile the document (defaults to |-shell-escape -halt-on-error|)
\end{itemize}
\subsubsection{Placeholders related to python}
@@ -2022,31 +2906,237 @@ Some placeholders are reserved only when dealing with \LaTeX{} code:
\subsection{Customize presets and create your own style}\label{sec:customize}
-Note that you can define your own presets simply by creating a new pgf style (please refer to tikz-pgf's documentation for more details). For instance, we defined the |tikz| style using:
+Note that you can define your own presets simply by creating a new pgf style (please refer to tikz-pgf's documentation for more details). For instance, we defined the |tikz| and |tikzpicture| presets using:
\begin{codeexample}[code only]
\robExtConfigure{
- tikz/.style={
+ new preset={tikz}{
latex,
add to preamble={\usepackage{tikz}},
- add before placeholder no space={__ROBEXT_MAIN_CONTENT__}{\begin{tikzpicture}},
- add to placeholder no space={__ROBEXT_MAIN_CONTENT__}{\end{tikzpicture}},
+ },
+ new preset={tikzpicture}{
+ tikz,
+ set placeholder={__ROBEXT_MAIN_CONTENT__}{\begin{tikzpicture}__ROBEXT_MAIN_CONTENT_ORIG__\end{tikzpicture}},
},
}
\end{codeexample}
-in order to automatically load |tikz| and add the surrounding |tikzpicture| (note that the style is always loaded \textbf{after} the definition of |__ROBEXT_MAIN_CONTENT__|, you can therefore do any postprocessing you like on this placeholder). You can also customize an existing style by adding stuff to it using |.append style|. For instance, here, we add the |shadows| library to the |tikz| preset by default:
+in order to automatically load |tikz| and add the surrounding |tikzpicture| when needed (note that the style is always loaded \textbf{after} the definition of |__ROBEXT_MAIN_CONTENT_ORIG__|, so in theory you could also modify it directly even if it is not recommended). You can also customize an existing style by adding stuff to it using |add to preset| (or |.append style| but make sure to double the hashes). For instance, here, we add the |shadows| library to the |tikz| preset by default:
\begin{codeexample}[width=0pt,vbox]
\robExtConfigure{
- tikz/.append style={
+ add to preset={tikz}{
add to preamble={\usetikzlibrary{shadows}},
},
}
See, tikz's style now packs the |shadows| library by default: %
- \begin{CacheMe}{tikz}[even odd rule]
+ \begin{CacheMe}{tikzpicture}[even odd rule]
\filldraw [drop shadow,fill=white] (0,0) circle (.5) (0.5,0) circle (.5);
\end{CacheMe}
\end{codeexample}
+\subsection{Cache automatically a given environment}\label{sec:wrapAutomatically}
+
+It might be handy to cache automatically a given environment: we already provide:\\ |\cacheTikz|\\
+to cache all tikz pictures (unless externalization is disabled), but we also provide tools to handle arbitrary environments.
+
+\begin{pgfmanualentry}
+ \extractcommand\robExtExternalizeAllTikzpicture\opt{\oarg{preset for tikz}}\opt{\oarg{preset for tikzpicture}}\opt{\oarg{delimiters}}\@@
+ \extractcommand\cacheTikz\opt{\oarg{preset for tikz}}\opt{\oarg{preset for tikzpicture}}\opt{\oarg{delimiters}}\@@
+ \pgfmanualbody
+ This will automatically cache all tikz pictures (both are alias, |\cacheTizk| is available from v2.0). Since v2.0, we added the delimiters options and we allow to specify custom presets for |tikz| and |tikzpicture|, and we parse |\tikz| as well (the |tikz| preset is now used by |\tikz| by default while the |tikzpicture| preset is used by |tikzpicture|). Note that we add an additional optional argument to the tikz picture via its first argument delimited by |delimiters| (defaults to |<>|) to specify preset options, which can for instance be practical to disable externalization on individual pictures. Cf.\ \cref{sec:disableExternalization} to see an example of use.
+\begin{codeexample}[width=0pt,vbox]
+\cacheTikz
+
+\def\whereIAm{(not cached)}
+\robExtConfigure{
+ add to preset={tikz}{
+ add to preamble={
+ \def\whereIAm{(cached)}
+ },
+ },
+}
+
+\tikz \node[fill=pink, rounded corners]{See that this syntax can be safely used. \whereIAm};
+
+\tikz<add to preamble={\def\sayHello#1{Hello #1!}}> \node[fill=green, rounded corners]{\sayHello{Alice} \whereIAm};
+
+\tikz<disable externalization> \node[fill=green, rounded corners]{Foo \whereIAm};
+\end{codeexample}
+Here is an example to specify arguments via parenthesis:
+\begin{codeexample}[width=0pt,vbox]
+% the first two arguments are the default presets used by \tikz and \tikzpicture
+\cacheTikz[tikz][tikzpicture][()]
+
+\def\whereIAm{(not cached)}
+\robExtConfigure{
+ add to preset={tikz}{
+ add to preamble={
+ \def\whereIAm{(cached)}
+ },
+ },
+}
+
+\tikz \node[fill=pink, rounded corners]{See that this syntax can be safely used. \whereIAm};
+
+\tikz(add to preamble={\def\sayHello#1{Hello #1!}}) \node[fill=green, rounded corners]{\sayHello{Alice} \whereIAm};
+
+\tikz(disable externalization) \node[fill=green, rounded corners]{Foo \whereIAm};
+\end{codeexample}
+
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\robExtDisableTikzpictureOverwrite\@@
+ \pgfmanualbody
+ This is useful to temporarily reset the current environment to their original value (since v2.0 it also resets other environments, not just |tikzpicture|). This must typically be called at the beginning of |command if no externalization| to avoid infinite recursion if you redefine it, but expect for this case the user is not expected to use this option.
+\end{pgfmanualentry}
+
+Let us say that you want to cache all elements of a given environment, like |minipage| or |zx-calculus| pictures (another package of mine):
+
+
+\begin{pgfmanualentry}
+ \extractcommand\cacheEnvironment\opt{\marg{delimiters}}\marg{name environment}\marg{default preset options}\@@
+ \pgfmanualbody
+ This will automatically cache the corresponding environment (but note that you still need to define it in the preamble of the cached files, for instance by loading the appropriate package):
+ \begin{codeexample}[width=0pt,vbox]
+ \cacheEnvironment{ZX}{latex, add to preamble={\usepackage{zx-calculus}}}
+ A ZX figure %
+ \begin{ZX}
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ*{a\pi} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ \end{ZX} and the same but aligned on the second line %
+ \begin{ZX}[mbr=2]
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ*{a\pi} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ \end{ZX}.
+ \end{codeexample}
+ You can of course configure them using globally defined configuration, but you can also provide arguments to a single picture using the delimiters |delimiters| that default to |<...>| as the optional argument, like: %
+ \begin{codeexample}[width=0pt,vbox]
+ \cacheEnvironment{ZX}{latex, add to preamble={\usepackage{zx-calculus}}}
+ \begin{ZX}<add to preamble={\usepackage{amsmath}}> % amsmath provides \text
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ{\text{yes}} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ \end{ZX}
+ \end{codeexample}
+ If you do not like |<>| or if your command already have this parameter, you can change it, for instance to get parens as delimiters, use:
+ \begin{codeexample}[width=0pt,vbox]
+ \cacheEnvironment[()]{ZX}{latex, add to preamble={\usepackage{zx-calculus}}}
+ \begin{ZX}(add to preamble={\usepackage{amsmath}}) % amsmath provides \text
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ{\text{yes}} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ \end{ZX}
+ \end{codeexample}
+ otherwise you must provide some presets arguments, possibly empty:\\
+ |\begin{someweirdenv}<><args to someweirdenv>|
+
+ You can also use this argument to disable externalisation on a per-picture basis:
+ \begin{codeexample}[width=0pt,vbox]
+ \cacheEnvironment{ZX}{latex, add to preamble={\usepackage{zx-calculus}}}
+ \begin{ZX}<disable externalization> % amsmath provides \text
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ*{a\pi} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ \end{ZX}
+ \end{codeexample}
+
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\cacheCommand\opt{\oarg{delimiter}}\marg{name command}\opt{\oarg{xparse signature}}\marg{default preset options}\@@
+ \pgfmanualbody
+ This will automatically cache the corresponding command, in a similar way to environment. It work exactly the same, except that we (usually) need to specify the signature of the command or it is impossible to know where the command stops. If the command is defined using xparse-compatible commands like |\NewDocumentCommand|, this detection is automatically done. Otherwise, you need to specify it in the xparse format: long story short, |O{foo}| is an optional argument with default value foo, |m| is a mandatory argument.
+
+ First, let us see an example with a command defined using xparse:
+ \begin{codeexample}[width=0pt,vbox]
+ % We cache the command \zx that is defined with NewDocumentCommand: no need to specify the signature
+ \cacheCommand{zx}{latex, add to preamble={\usepackage{zx-calculus}}}
+ A ZX figure %
+ \zx{
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ*{a\pi} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ } and the same but aligned on the second line %
+ \zx[mbr=2]{
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ*{a\pi} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ }.
+ \end{codeexample}
+
+ You can of course configure them using globally defined configuration, but you can also provide arguments to a single picture using the delimiters that default to |<>| as the optional argument, like: %
+ \begin{codeexample}[width=0pt,vbox]
+ \cacheCommand{zx}{latex, add to preamble={\usepackage{zx-calculus}\def\hello#1{Hello #1.}}}
+ \zx<add to preamble={\usepackage{amsmath}\def\bye#1{Bye #1.}}>[mbr=1]{ % amsmath provides \text
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ{\text{\hello{Alice}}} \\
+ \zxZ{\beta} \rar & \zxZ{\text{\bye{Bob}}}
+ }
+ \end{codeexample}
+ or with parens as delimiters:
+ \begin{codeexample}[width=0pt,vbox]
+ \cacheCommand[()]{zx}{latex, add to preamble={\usepackage{zx-calculus}}}
+ \zx(add to preamble={\usepackage{amsmath}})[mbr=1]{ % amsmath provides \text
+ \zxX{\alpha} \rar \ar[d,C] & \zxZ{\text{yes}} \\
+ \zxZ{\beta} \rar & \zxX*{b\pi}
+ }
+ \end{codeexample}
+
+ Here is an example with a command not defined with |\NewDocumentCommand| (we also show how you can use the optional argument to disable externalisation on a per-picture basis):
+\begin{codeexample}[width=0pt,vbox]
+\def\fromWhere{I am not cached}
+\newcommand{\myMacroNotDefinedWithNewDocumentCommand}[3][default value]{
+ Optional argument 1: #1,
+ Argument 2: #2,
+ Argument 3: #3 (\fromWhere).
+}
+\cacheCommand{myMacroNotDefinedWithNewDocumentCommand}[O{default value}mm]{
+ latex,
+ add to preamble={%
+ \def\fromWhere{I am cached}
+ \newcommand{\myMacroNotDefinedWithNewDocumentCommand}[3][default value]{
+ Optional argument 1: #1,
+ Argument 2: #2,
+ Argument 3: #3 (\fromWhere).
+ }
+ }
+}
+
+\myMacroNotDefinedWithNewDocumentCommand{second arg}{last arg}\\
+\myMacroNotDefinedWithNewDocumentCommand<disable externalization>{second arg}{last arg}
+\end{codeexample}
+
+\end{pgfmanualentry}
+
+\paragraph{Defining its own macro without repeating its definition.}
+Note that when you define yourself a macro function, the above structure might not be optimal as you need to define the macro in the main document (in case you disable the externalization) and in the template. One option to avoid repeated code is to write the definition in a common input file (see \cref{sec:dependencies}), but you might prefer to keep everything in a single file. In that case, you can simply wrap your function into |cacheMe| yourself. Say you want your function to draw a circle like, |\tikz \draw[fill=#2] (0,0) circle [radius=#1];|, then wrap in inside |CacheMe|:
+
+\begin{codeexample}[width=0mm,vbox]
+% D<>{} is an optional argument enclosed in <>, we use this to pass arguments to CacheMe
+\NewDocumentCommand{\drawMyCircle}{D<>{}O{2mm}m}{
+ \begin{CacheMe}{tikz, #1}
+ \tikz \draw[fill=#3] (0,0) circle [radius=#2];
+ \end{CacheMe}
+}
+
+You can externalize it \drawMyCircle{pink} %
+or disable externalization \drawMyCircle<disable externalization>[4mm]{red}.
+\end{codeexample}
+
+\paragraph{Manually wrap a command.} In some more advanced cases, if you do not know the definition of the command and if |\cacheCommand| does not work (e.g. the number of mandatory argument depends on the first argument), you can wrap it manually. To do so, first copy first your command using |\DeclareCommandCopy{\robExtCommandOrigNAMEOFCOMMAND}{\NAMEOFCOMMAND}| and run |\robExtAddToCommandResetList{NAMEOFCOMMAND}| (this is needed to disable externalization), and override the command by wrapping it into a cache. Make sure to add |\def\robExtCommandOrigName{NAMEOFCOMMAND}| at the beginning of the function or |disable externalization| will not work:
+
+\begin{codeAndResult}
+Original command: \zx{\zxZ{\alpha} \rar & \zxX{\beta}}. %
+\DeclareCommandCopy{\robExtCommandOrigzx}{\zx}% used to recover the original function
+\robExtAddToCommandResetList{zx}% let us know that this function should be reset when externalization is disabled
+\DeclareDocumentCommand{\zx}{D<>{}O{}m}{%
+ \def\robExtCommandOrigName{zx}%
+ \begin{CacheMe}{latex, add to preamble={\usepackage{zx-calculus}}, #1}%
+ \zx[#2]{#3}%
+ \end{CacheMe}%
+}
+This is cached \zx<>{\zxZ{\alpha} \rar & \zxX{\beta}}, you can add options like %
+\zx<add to preamble={\usepackage{amsmath}}>{\zxZ{\alpha} \rar & \zxX{\text{Hey}}} %
+and we can disable the externalization: %
+\zx<disable externalization>{\zxZ{\alpha} \rar & \zxX{\text{Hey}}}.
+\end{codeAndResult}
+
+You can do a similar trick for environment, by using instead |\NewEnvironmentCopy{robExtEnvironmentOrigNAMEENV}{NAMEENV}| |\robExtAddToEnvironmentResetList{NAMEENV}| and |\def\robExtEnvironmentOrigName{NAMEENV}|.
+
\subsection{Operations on the cache}\label{sec:operationsCache}
Every time we compile a document, we create automatically a bunch of files:
@@ -2082,6 +3172,13 @@ When enabling the manual mode (useful if we don't want to enable |-shell-escape|
}
\end{verbatim}
+or the fallback to manual mode (it will only enable the manual mode if |-shell-escape| is disabled):
+\begin{verbatim}
+\robExtConfigure{
+ enable fallback to manual mode,
+}
+\end{verbatim}
+
the library creates a file |JOBNAME-robExt-compile-missing-figures.sh| that contains the instructions to build the figures that are not yet in the cache (each line contains the compilation command to run). On Linux (or on Windows with bash/cygwin/… installed, it possibly even work out of the box without) you can easily execute them using:
\begin{verbatim}
@@ -2089,23 +3186,163 @@ bash JOBNAME-robExt-compile-missing-figures.sh
\end{verbatim}
-\subsection{How to debug}
+\subsection{How to debug}\label{sec:debug}
+
+If for some reasons you are unable to understand why a build fails, first check if you compiled your document with |-shell-escape| (not that this must appear \textbf{before} the filename). Then, you can look at the log file to get more advices: when a cached document is compiled, we always write the full compilation command before compiling the file in the log file. This way, you can easily check the content of the file and see why it fails to compile. The compilation errors are also displayed directly in the output, and you can read the log file for details.
+
+You might often get an error |! Missing $ inserted.|: this is typically when a placeholder was left unreplaced (e.g.\ you forgot to define it, import it, or you forgot to wrap a command in |\evalPlaceholder{}|): since \LaTeX{} is asked to typeset |__something__|, it thinks that you are trying to write a subscript, and asks you to start first the math mode.
+
+To get more advanced info during the compilation command, set the style |more logs| (that does |\def\robExtDebugMessage#1{\message{^^J[robExt] #1}}|) in order to print some messages on the replacement process (there is also |\robExtDebugWarning| for more important messages, but it prints the logs by default.
+
+Then, it is often handy to check the content of the generated template. You can either get the name in the log, via |name output|, or print it directly in the file:
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/debug\@nil
+ \extractkey/robExt/print command and source\@nil
+ \makeatother%
+ \pgfmanualbody
+You can also use |debug| (or its alias |print command and source|) in order to disable the compilation and print instead the compilation command and the source file:
+
+\begin{codeexample}[width=0pt,vbox]
+ \begin{tikzpictureC}<debug>[baseline=(A.base)]
+ \node[fill=red, rounded corners](A){My node that respects baseline \ding{164}.};
+ \node[fill=red, rounded corners, opacity=.3,overlay] at (A.north east){I am an overlay text};
+ \end{tikzpictureC}
+\end{codeexample}
+\begin{codeexample}[width=0pt,vbox]
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\robExtShowPlaceholder\opt{*}\marg{placeholder name}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/show placeholder=\marg{placeholder name}\@nil
+ \makeatother%
+ \pgfmanualbody
+ |\robExtShowPlaceholder{__ROBEXT_MAIN_CONTENT__}| will show in the terminal the content of the placeholder. Use the start not to pause.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\robExtShowPlaceholders\opt{*}\@@
+ \extractcommand\robExtShowPlaceholdersContents\opt{*}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/show placeholders\@nil
+ \extractkey/robExt/show placeholders contents\@nil
+ \makeatother%
+ \pgfmanualbody
+ Show all imported placeholders and their content. Use the start not to pause.
+\end{pgfmanualentry}
+
+
+\subsection{Advanced optimizations}\label{sec:advancedOperations}
+
+We made a number of optimizations to get near instant feedback on documents having hundreds of pictures, basically by saying which placeholder should be replaced, in which order, when to stop replacing placeholders, and possibly by compiling templates (see \cref{sec:compilePreset}). Most of them are invisible to the end user and pre-configured for presets like |latex| or when compiling a preset, but you might want to also use them on your own.
+
+First note that the order used to import placeholders is important, as it will first replace the first imported placeholders: so if you imported the placeholders in the right order, a single loop should be enough to replace them all, otherwise you might need $n$ loops if you need to replace $n$ placeholders (the basic evaluation procedure just loops over placeholders and replace all occurrences in the string until there is either no remaining placeholders (see below), or if you obtain the same result after two loops).
+
+
+\begin{pgfmanualentry}
+ \extractcommand\onlyPlaceholdersInCompilationCommand\marg{list,of,placeholders}\@@
+ \extractcommand\firstPlaceholdersInCompilationCommand\marg{list,of,placeholders}\@@
+ \extractcommand\onlyPlaceholdersInTemplate\marg{list,of,placeholders}\@@
+ \extractcommand\firstPlaceholdersInTemplate\marg{list,of,placeholders}\@@
+ \pgfmanualbody
+ Using these commands (possibly inside |/utils/exec={\yourcommand{foo}}| in a style), you will tell to the system to evaluate the compilation/template placeholders (depending on the name of the command) only using the placeholders in the argument, or (for the commands starting with |first|), by starting with the placeholders in argument before continuing with others placeholders.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/all placeholders have underscores\@nil
+ \extractkey/robExt/not all placeholders have underscores\@nil
+ \makeatother%
+ \pgfmanualbody
+In order to know when to stop replacing placeholders earlier (i.e.\ without running until it converges), it is practical to know how placeholders look like in order to stop before. This (enabled by default) says to the library that all placeholders should start with two underscores |__|, allowing us to easily check if a string contains a placeholder. If you want to use placeholders with fancy names and no underscores, disable this feature (but it might be a bit slower).
+\end{pgfmanualentry}
+
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/do not load special placeholders\@nil
+ \extractkey/robExt/load special placeholders\@nil
+ \makeatother%
+ \pgfmanualbody
+ Similarly, to save some time, we do not import some special placeholders and only replace them manually at the end, the list being: |__ROBEXT_OUTPUT_PREFIX__|, |__ROBEXT_SOURCE_FILE__|, |__ROBEXT_OUTPUT_PDF__|, |__ROBEXT_WAY_BACK__|, |__ROBEXT_CACHE_FOLDER__|. If for some reasons you do want to import them earlier, you can do it this way.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/disable placeholders\@nil
+ \extractkey/robExt/enable placeholders\@nil
+ \makeatother%
+ \pgfmanualbody
+ To save even more time, you can disable the placeholder system completely, and only replace the following placeholders: |__ROBEXT_MAIN_CONTENT__|, |__ROBEXT_LATEX_PREAMBLE__| and |__ROBEXT_MAIN_CONTENT_ORIG__|. This is done notably inside |new compiled preset| in order to speed up the compilation by maybe a factor of 1.5 or 2, but then you cannot use any other placeholders. Note that the default presets like |latex| enable placeholders, so you should be able to call |latex| inside a compiled template to come back to the uncompiled version.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/disable import mechanism\@nil
+ \extractkey/robExt/enable optimizations\@nil
+ \makeatother%
+ \pgfmanualbody
+ If you disable the import mechanism (enabled by default), it will do an |\importAllPlaceholders| while evaluating the template. This is not recommended as it is quite inefficient, it is better to selectively import the group you need.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/disable optimizations\@nil
+ \extractkey/robExt/enable optimizations\@nil
+ \makeatother%
+ \pgfmanualbody
+
+\end{pgfmanualentry}
-If for some reasons you are unable to understand why a build fails, first check if you compiled your document with |-shell-escape| (not that this must appear \textbf{before} the filename). Then, you can look at the log file to get more advices: when a cached document is compiled, we always write the full compilation command before compiling the file in the log file. This way, you can easily check the content of the file and see why it fails to compile. The compilation errors are also displayed directly in the output.
-You might often get an error |! Missing $ inserted.|: this is typically when a placeholder was left unreplaced (e.g.\ you forgot to define it, or you forgot to wrap a command in |\evalPlaceholder{}|): since \LaTeX{} is asked to typeset |__something__|, it thinks that you are trying to write a subscript, and asks you to start first the math mode.
\section{TODO and known bugs:}
\begin{itemize}
-\item See how to deal with label and references inside pictures (without disabling externalization).
-\item We should create more pre-made settings, e.g. for tikz-cd, zx-calculus etc.
+\item See how to deal with label, links and cite inside pictures (without disabling externalization). For label and links, I have a proof of concept, I ``just'' need to write it down. \url{https://tex.stackexchange.com/questions/695277/clickable-includegraphics-for-cross-reference-data}
\item Deal with remember picture
+\item I tried many different options to optimize the compilation time, so the code is a bit cluttered now. Would be cool to reorganize.
+\item The doc more or less describes all features, but I might made tons of typo and forgot to document some advanced commands. But should be good enough for normal usage.
\end{itemize}
\section{Acknowledgments}
-I am deeply indebted to many users on \url{tex.stackexchange.com} that made the writing of this library possible. I can't list you all, but thank you so much!
+I am deeply indebted to many users on \url{tex.stackexchange.com} that made the writing of this library possible. I can't list you all, but thank you so much! A big thanks also to the project \url{https://github.com/sasozivanovic/memoize/} from which I borrowed most of the code to automatically wrap commands.
+
+\section{Changelog}
+
+\begin{itemize}
+\item v2.0:
+ \begin{itemize}
+ \item \textbf{not backward compatible}: the preset |tikzpicture| should be used instead of |tikz|: |tikz| does not wrap anymore its content into |\begin{tikzpicture}| in order to be usable inside the command version |\tikz| (but |tikzpicture| does load |tikz| first). Moreover, all arguments to |tikzpictureC| or |tikzpicture| (if you loaded |cacheTikz|) should be specified in the first argument, using |<your options>|. This is used to provide a more uniform interface with the new |\cacheEnvironment| command. Hopefully this should \textbf{not cause too much trouble} since the first version of the library has been published on CTAN only a few days ago.
+ \item not really compatible: Renamed some latex placeholders to prefix all of them with |__ROBEXT_LATEX_|. Should not be a problem if you used the style made to change them.
+ \item Added an alias to |\robExtExternalizeAllTikzpictures| called |\cacheTikz|. Now, this also configures |\tikz|.
+ \item You can now use ampersands etc freely thanks to lrbox.
+ \item You can now automatically cache environments using |\cacheEnvironment| and commands using |\cacheCommand|.
+ \item We provide |new preset| and |add to preset| to avoid doubling the number of hashes.
+ \item We provide new functions like |\setPlaceholderRecReplaceFromList| to only expand a subset of placeholders.
+ \item An error message is given if you forget to set a template.
+ \item Add |enable fallback to manual mode| to fallback to manual mode only if shell escape is missing.
+ \item Allow restricted mode
+ \item |debug| mode available
+ \item Rename |set subfolder and way back| to |set cache folder and way back| (in a backward compatible way)
+ \item Waaaaaaay more efficient. Also added a method to compile presets.
+ \item I added the import system for efficiency reasons (not present in v1.0 at all). Note that I also added some other functions that I forgot to notify as new in the doc...
+ \end{itemize}
+\end{itemize}
+
+\printindex
\end{document}
% Local Variables:
diff --git a/systems/texlive/tlnet/tlpkg/TeXLive/TLPDB.pm b/systems/texlive/tlnet/tlpkg/TeXLive/TLPDB.pm
index 3bac015450..d19c812cfb 100644
--- a/systems/texlive/tlnet/tlpkg/TeXLive/TLPDB.pm
+++ b/systems/texlive/tlnet/tlpkg/TeXLive/TLPDB.pm
@@ -1,4 +1,4 @@
-# $Id: TLPDB.pm 65964 2023-02-20 17:13:02Z karl $
+# $Id: TLPDB.pm 68283 2023-09-15 13:11:11Z preining $
# TeXLive::TLPDB.pm - tlpdb plain text database files.
# Copyright 2007-2023 Norbert Preining
# This file is licensed under the GNU General Public License version 2
@@ -7,7 +7,7 @@
use strict; use warnings;
package TeXLive::TLPDB;
-my $svnrev = '$Revision: 65964 $';
+my $svnrev = '$Revision: 68283 $';
my $_modulerevision = ($svnrev =~ m/: ([0-9]+) /) ? $1 : "unknown";
sub module_revision { return $_modulerevision; }
@@ -2107,14 +2107,27 @@ sub remove_package {
0, # tlpdbopt_desktop_integration, desktop part
$localtlpdb->option("post_code"));
}
- #
- my @removals = &TeXLive::TLUtils::removed_dirs (@goodfiles);
+ # we want to check whether we can actually remove files
+ # there might be various reasons that this fails, like texmf-dist
+ # directory suddently becoming ro (for whatever definition of
+ # suddenly).
+ my (%by_dirs, %removed_dirs) = &TeXLive::TLUtils::all_dirs_and_removed_dirs (@goodfiles);
+ my @removals = keys %removed_dirs;
+
+ # we have already check for the existence of the dirs returned
+ for my $d (keys %by_dirs) {
+ if (! &TeXLive::TLUtils::dir_writable($d)) {
+ tlwarn("TLPDB: directories are not writable, cannot remove files: $d\n");
+ return 0;
+ }
+ }
+
# now do the removal
for my $entry (@goodfiles) {
- unlink $entry;
+ unlink $entry or tlwarn("Could not unlink $entry: $!\n");
}
for my $d (@removals) {
- rmdir $d;
+ rmdir $d or tlwarn("Could not remove directory $d: $!\n")
}
$localtlpdb->remove_tlpobj($pkg);
TeXLive::TLUtils::announce_execute_actions("disable", $tlp);
@@ -3000,4 +3013,4 @@ GNU General Public License Version 2 or later.
### tab-width: 2
### indent-tabs-mode: nil
### End:
-# vim:set tabstop=2 expandtab autoindent: #
+# vim:set tabstop=2 shiftwidth=2 expandtab autoindent: #
diff --git a/systems/texlive/tlnet/tlpkg/TeXLive/TLUtils.pm b/systems/texlive/tlnet/tlpkg/TeXLive/TLUtils.pm
index c8b1260fcb..30d53ad7c7 100644
--- a/systems/texlive/tlnet/tlpkg/TeXLive/TLUtils.pm
+++ b/systems/texlive/tlnet/tlpkg/TeXLive/TLUtils.pm
@@ -1,4 +1,4 @@
-# $Id: TLUtils.pm 66420 2023-03-07 08:30:26Z preining $
+# $Id: TLUtils.pm 68283 2023-09-15 13:11:11Z preining $
# TeXLive::TLUtils.pm - the inevitable utilities for TeX Live.
# Copyright 2007-2023 Norbert Preining, Reinhard Kotucha
# This file is licensed under the GNU General Public License version 2
@@ -8,7 +8,7 @@ use strict; use warnings;
package TeXLive::TLUtils;
-my $svnrev = '$Revision: 66420 $';
+my $svnrev = '$Revision: 68283 $';
my $_modulerevision = ($svnrev =~ m/: ([0-9]+) /) ? $1 : "unknown";
sub module_revision { return $_modulerevision; }
@@ -59,6 +59,8 @@ C<TeXLive::TLUtils> - TeX Live infrastructure miscellany
TeXLive::TLUtils::copy($file, $target_dir);
TeXLive::TLUtils::touch(@files);
TeXLive::TLUtils::collapse_dirs(@files);
+ TeXLive::TLUtils::all_dirs_and_removed_dirs(@files);
+ TeXLive::TLUtils::dirs_of_files(@files);
TeXLive::TLUtils::removed_dirs(@files);
TeXLive::TLUtils::download_file($path, $destination);
TeXLive::TLUtils::setup_programs($bindir, $platform);
@@ -210,6 +212,8 @@ BEGIN {
&copy
&touch
&collapse_dirs
+ &all_dirs_and_removed_dirs
+ &dirs_of_files
&removed_dirs
&install_package
&install_packages
@@ -1614,30 +1618,14 @@ sub collapse_dirs {
return @ret;
}
-=item C<removed_dirs(@files)>
-
-Returns all the directories from which all content will be removed.
-
-Here is the idea:
-
-=over 4
-
-=item create a hashes by_dir listing all files that should be removed
- by directory, i.e., key = dir, value is list of files
-
-=item for each of the dirs (keys of by_dir and ordered deepest first)
- check that all actually contained files are removed
- and all the contained dirs are in the removal list. If this is the
- case put that directory into the removal list
-
-=item return this removal list
+=item C<dirs_of_files(@files)>
-=back
+Returns all the directories in which at least one of the given
+files reside.
=cut
-sub removed_dirs {
+sub dirs_of_files {
my (@files) = @_;
- my %removed_dirs;
my %by_dir;
# construct hash of all directories mentioned, values are lists of the
@@ -1663,6 +1651,21 @@ sub removed_dirs {
$by_dir{$d} = \@a;
}
+ return %by_dir;
+}
+
+=item C<all_dirs_and_removed_dirs(@files)>
+
+Returns all the directories for files and those from which all
+content will be removed.
+
+=cut
+
+sub all_dirs_and_removed_dirs {
+ my (@files) = @_;
+ my %removed_dirs;
+ my %by_dir = dirs_of_files(@files);
+
# for each of our directories, see if we are removing everything in
# the directory. if so, return the directory; else return the
# individual files.
@@ -1698,9 +1701,37 @@ sub removed_dirs {
$removed_dirs{$d} = 1;
}
}
+ return (%by_dir, %removed_dirs);
+}
+
+=item C<removed_dirs(@files)>
+
+Returns all the directories from which all content will be removed.
+
+Here is the idea:
+
+=over 4
+
+=item create a hashes by_dir listing all files that should be removed
+ by directory, i.e., key = dir, value is list of files
+
+=item for each of the dirs (keys of by_dir and ordered deepest first)
+ check that all actually contained files are removed
+ and all the contained dirs are in the removal list. If this is the
+ case put that directory into the removal list
+
+=item return this removal list
+
+=back
+=cut
+
+sub removed_dirs {
+ my (@files) = @_;
+ my (%by_dir, %removed_dirs) = all_dirs_and_removed_dirs(@files);
return keys %removed_dirs;
}
+
=item C<time_estimate($totalsize, $donesize, $starttime)>
Returns the current running time and the estimated total time
@@ -5275,4 +5306,4 @@ GNU General Public License Version 2 or later.
### tab-width: 2
### indent-tabs-mode: nil
### End:
-# vim:set tabstop=2 expandtab: #
+# vim:set tabstop=2 shiftwidth=2 expandtab: #
diff --git a/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl b/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl
index c3cc3ffa8c..e5dc44f0d6 100644
--- a/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl
+++ b/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl
@@ -29,6 +29,9 @@ $mirrors = {
'Hong Kong' => {
'https://mirror-hk.koddos.net/CTAN/' => 1,
},
+ 'India' => {
+ 'https://mirror.niser.ac.in/ctan/' => 1,
+ },
'Indonesia' => {
'http://repo.ugm.ac.id/ctan/' => 1,
'https://mirror.unpad.ac.id/ctan/' => 1,
@@ -134,6 +137,7 @@ $mirrors = {
'https://ctan.gust.org.pl/tex-archive/' => 1,
'https://polish-mirror.evolution-host.com/ctan/' => 1,
'https://repo.skni.umcs.pl/ctan/' => 1,
+ 'https://sunsite.icm.edu.pl/pub/CTAN/' => 1,
},
'Portugal' => {
'https://ftp.eq.uc.pt/software/TeX/' => 1,
@@ -157,7 +161,6 @@ $mirrors = {
'https://ftpmirror1.infania.net/mirror/CTAN/' => 1,
},
'Switzerland' => {
- 'https://mirror.foobar.to/CTAN/' => 1,
'https://mirror.init7.net/ctan/' => 1,
'https://mirror.metanet.ch/tex-archive/' => 1,
},
diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb b/systems/texlive/tlnet/tlpkg/texlive.tlpdb
index 5f750bcfaa..5b857831fd 100644
--- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb
+++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb
@@ -26,11 +26,11 @@ depend container_split_src_files/1
depend frozen/0
depend minrelease/2016
depend release/2023
-depend revision/68280
+depend revision/68289
name 00texlive.image
category TLCore
-revision 68280
+revision 68286
shortdesc TeX Live files only in the source repository
longdesc The files here are not copied by the installer and containers
longdesc are not built for them; they exist only in the source
@@ -4801,7 +4801,7 @@ depend setting_available_architectures:aarch64-linux amd64-freebsd amd64-netbsd
name 00texlive.installer
category TLCore
-revision 68275
+revision 68282
shortdesc TeX Live standalone installer package
longdesc This package defines the files to go into the installer
longdesc archives (install-tl-unx.tar.gz, install-tl.zip) built by the
@@ -35170,16 +35170,16 @@ catalogue-topics book-pub class doc-templ expl3
name beebe
category Package
-revision 68190
+revision 68282
catalogue biblio
shortdesc A collection of bibliographies
relocated 1
longdesc A collection of BibTeX bibliographies on TeX-related topics
longdesc (including, for example, spell-checking and SGML). Each
longdesc includes a LaTeX wrapper file to typeset the bibliography.
-containersize 907040
-containerchecksum 8b3e3505944dd04d2412626e41f9d52c1525cdd162bc12600896d1f1882bb4fae07e10c7dbe669f72a7fc5e5cb93c28a0affc6c3301a93491df9078c46d272ea
-runfiles size=2233
+containersize 907204
+containerchecksum 4574e69eb21f09b27671a52b5beccd3fc96816e24da2f2e0da012e43227a8b1d69b4d26c2acf581641b672fdc68d6a31179a7cd4f76036201addacbfb888925b
+runfiles size=2234
RELOC/bibtex/bib/beebe/epodd.bib
RELOC/bibtex/bib/beebe/font.bib
RELOC/bibtex/bib/beebe/printing-history.bib
@@ -128216,7 +128216,7 @@ catalogue-topics font-doc
name fontools
category Package
-revision 65706
+revision 68285
shortdesc Tools to simplify using fonts (especially TT/OTF ones)
longdesc This package provides tools to simplify using OpenType fonts
longdesc with LaTeX. By far the most important program in this bundle is
@@ -128230,11 +128230,11 @@ longdesc - re-encode .afm files, ot2kpx - extract kerning pairs from
longdesc OpenType fonts, splitttc - split an OpenType Collection file
longdesc (ttc or otc) into individual fonts.
depend fontools.ARCH
-containersize 55340
-containerchecksum a4cd3009c98502534f3c54d40fb22d788bcdfd474ba6bfc1b7010aa4d3471f468cd54a5d5c292d5afe685f9e4d99c023b8f78f302792dd1b381418042d96f47c
-doccontainersize 129664
-doccontainerchecksum 0506f6e9d0e0ae4fe4bb15303e2abde50a076899e4330a7d68f875abeaacff999cbab779bb368da5c717370e7cf885333c1479d6e795da4e387edd4656c30933
-docfiles size=56
+containersize 55892
+containerchecksum 0a9388c29a2797cddc72e8948d68653bcad66e0cd4082a4212ec3208e4be0426028c51f6a2efe5e9c89f8c3b092be557513ef814b0f07f8ebfc92f0ad3bd0007
+doccontainersize 130928
+doccontainerchecksum b885c1b607ca56d1ac8a107b648156d2dbf1c63174fb799c0942520e591b0f770dca49bc424aad4c50920c3b9059dae272fd0cdbd93d828070ee6c585e5360d4
+docfiles size=57
texmf-dist/doc/man/man1/afm2afm.1
texmf-dist/doc/man/man1/afm2afm.man1.pdf
texmf-dist/doc/man/man1/autoinst.1
@@ -128244,7 +128244,7 @@ docfiles size=56
texmf-dist/doc/support/fontools/GPLv2.txt
texmf-dist/doc/support/fontools/README details="Bundle readme"
texmf-dist/doc/support/fontools/splitttc
-runfiles size=77
+runfiles size=78
texmf-dist/fonts/enc/dvips/fontools/fontools_cs.enc
texmf-dist/fonts/enc/dvips/fontools/fontools_l7x.enc
texmf-dist/fonts/enc/dvips/fontools/fontools_lgr.enc
@@ -210669,7 +210669,7 @@ catalogue-version 1.1
name minted
category Package
-revision 68252
+revision 68286
shortdesc Highlighted source code for LaTeX
relocated 1
longdesc The package that facilitates expressive syntax highlighting in
@@ -210690,16 +210690,16 @@ depend pdftexcmds
depend tools
depend xcolor
depend xstring
-containersize 10088
-containerchecksum c6562bd27f0239728da51bd72fd611cb4f17570df5d9844e46bbd27d81117ebf5f2eedbfc7c47fd463ed7546384c99f04f8950e22daf2e9dfee67650970a0f67
+containersize 10092
+containerchecksum 7fcc30c7722646b19dd9c656759ff39d053ef9fe60ff1228b5d7c33c3bc15dfadb8f2e51a1355c8478f5e145e4cc473967316abd914a54a2d6c734f53a759d77
doccontainersize 849336
-doccontainerchecksum 6d8289670a699bfcd3c7368c5c149f9624fae047432c73db408a5d88e7cd986635832cd5c56996af8e5859ed8a882023a927cd2f22564f14fe9ea5ee0f84e776
+doccontainerchecksum 7f99f31442aa7bc4ea6520e9363efb92918ca8fe7a055da7df3457acd3320e634c55f6ac785890e2fbaf3b71b7c06dacad891edce7263f1e2ae29257ae50c508
docfiles size=215
RELOC/doc/latex/minted/DEPENDS.txt
RELOC/doc/latex/minted/README details="Readme"
RELOC/doc/latex/minted/minted.pdf details="Package documentation"
-srccontainersize 47724
-srccontainerchecksum 466f34ae891af02f2bc97551ea6b4b4700da347f16899ac10d4b1cc82ea79feee4f9448bf9f5636965c493fbd4288c8a7ba58ba3a60c9b1d9ded4818df249781
+srccontainersize 47728
+srccontainerchecksum db62751e14d97bdf6b7e5f64d9cf66281b63c95531a162813c43a47a011e1212a10a70d5c319a55ccf32ccddda06c14ed2a881a46ad99d5d1e9e0bf6e4b954a9
srcfiles size=54
RELOC/source/latex/minted/Makefile
RELOC/source/latex/minted/minted.dtx
@@ -286577,7 +286577,7 @@ catalogue-version 1.6a
name simpleicons
category Package
-revision 68208
+revision 68284
shortdesc Simple Icons for LaTeX
relocated 1
longdesc Similar to FontAwesome icons being provided on LaTeX by the
@@ -286585,10 +286585,10 @@ longdesc fontawesome package, this package aims to do the same with
longdesc Simple Icons. For reference, visit their website:
longdesc https://simpleicons.org/.
execute addMap simpleicons.map
-containersize 2985208
-containerchecksum fa4fa4cf49e8e411edad0101d65dd5cf0d9335af5c88f4d4f457b29d919bed48852c6cbe0aaa97c592662af6eb65ec3a1df22a9a72ba43cec5b4e5200f562225
-doccontainersize 2196936
-doccontainerchecksum 2eba0e25caca15035b62266b3fa80e45f45e5343d249a5deca207247c9205622f0cb84ca19a654bd1fe0ff65a78cdab7eed590fcc4ba9f3526b33ff7595417ee
+containersize 2985204
+containerchecksum a074b0b4d440c1f5f994f5d13ca34a3ceea1903699dc010a1c8259b95266b3e78ca5f3fee6fa1c10924a50966fe46272d04d633dbb17e63593cf6076ba042a26
+doccontainersize 2197092
+doccontainerchecksum b8b1ea741872f9d2b201a09a36c7a3794f6b4993f458fdbdd7cf321234345b9d1c1707ac29413a9203324b03a43dcca6c756c8758a2ae0e8dfdf31a4d758bc5a
docfiles size=571
RELOC/doc/fonts/simpleicons/README.md details="Readme"
RELOC/doc/fonts/simpleicons/bindings.tex
@@ -286639,7 +286639,7 @@ catalogue-contact-repository https://github.com/ineshbose/simple-icons-latex
catalogue-ctan /fonts/simpleicons
catalogue-license cc-by-1
catalogue-topics font font-symbol font-supp-symbol font-otf font-type1
-catalogue-version 9.13.0
+catalogue-version 9.14.0
name simpleinvoice
category Package
@@ -315584,7 +315584,7 @@ docfiles size=376
name texlive-scripts
category TLCore
-revision 68275
+revision 68282
shortdesc TeX Live infrastructure programs
longdesc Includes install-tl, tl-portable, rungs, etc.; not needed for
longdesc tlmgr to run but still ours. Not included in tlcritical.
@@ -315592,10 +315592,10 @@ depend texlive-scripts.ARCH
depend texlive.infra
execute addMap mathpple.map
postaction shortcut type=menu name="TeX Live command-line" cmd=TEXDIR/tlpkg/installer/tl-cmd.bat
-containersize 114108
-containerchecksum 0303774013270ec58ab427a00cdd614b3167bcb0ac9ba100cac459aa040be9435b24334faf6602811716ced969eb4c9a4a36d62cfc36da5b39353a5707212a91
-doccontainersize 429652
-doccontainerchecksum 7778f148f40c8dfc58d058a0fca0d46380613993b785ce7e0dc9af3a12729ff3e9b434fd5b02e19784174660d3c3f1809159474442d91549533fe0a054a96e14
+containersize 114140
+containerchecksum cc51683bcc3653e98cf930d69802c9e0451a10310d09192744e4dffbecae7cd5c4d98dc0060dd58358e5c0c51e1625414e0e34d0b7fee32b5a50c541b2761f67
+doccontainersize 429676
+doccontainerchecksum ccc43c1c215e64061da38a1e10da8437c3e628f148f1e8507538ae219d6bf955627a5c3e3434cae3ce26ce9ee6fd71e0b592a8dbc1ecc9303d5a2bd204b7570a
docfiles size=550
doc.html
texmf-dist/doc/man/man1/fmtutil-sys.1
diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5
index 23ae8183cb..9fd0c0e541 100644
--- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5
+++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5
@@ -1 +1 @@
-d399a5bc7dc56b8003daa26510862b82 texlive.tlpdb
+825168093a27ad218fc60cd8ad195ebd texlive.tlpdb
diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512
index 73081812c7..37760f297b 100644
--- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512
+++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512
@@ -1 +1 @@
-9e87e5f055f4048365a7d8702e821612555705604f2094f61b47514b663f9026bf635214a3e4101bd125231c47cfe404c5b1d4aeb03574f6386471da02cb5374 texlive.tlpdb
+4514839313a7a9b9203ae120f3f258c72c6f12f71d9a5758e7f82c05798dfa776f2009ce1deb6f03312900d5cd551797760002cc075a1bb0f4419ef58e7af5de texlive.tlpdb
diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc
index 3aa548444a..e38246afe1 100644
--- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc
+++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc
@@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE-----
-iQEzBAEBCgAdFiEE2PL4YFeoV+QqiBBqTOGHfhlDjHAFAmUDmwgACgkQTOGHfhlD
-jHBo6wf/cgi5LcsCAnxEjyxp7Sgp2GefDZ0/gqvooOx+ersD7Vz6gsyYM+vmeZiu
-nQRR2+w4S6c10bkJcRvbnORAnJUdHSfnEFEc9d9ds48LAhygdRGBPgV+OO04ODuh
-vT/PMaCxQV+sKlL3XMBPk50tJWzBagjp0Cl2ww84aA4+jOrZnwSm74+qkfsSP251
-Xba3hFjn1rg3ZWV0vsMecaKneZLGlELrHhMjszfvMdAgdg+1bAxqDKSzaY83eaAT
-bBHbFR2gyyArhkEasYx81A6PKKTl5Z0Iw1L6BxZJ4rgfR5gxB0LOHe1ifMkWy7fm
-sQAUaz+VKWPwujLSq+u2e8xNMx+aFQ==
-=j0wk
+iQEzBAEBCgAdFiEE2PL4YFeoV+QqiBBqTOGHfhlDjHAFAmUE7GEACgkQTOGHfhlD
+jHBwfwgAp+TLF/ApDFlfRULhKPDPM9r+c6RlgodUCAmsuKfWRGX/VpbI8oV7rw2P
+d8+FnOWYfgBM09bvhcOj+NcQYYB7ptCym0qO0ALYuUKX6EF7kt1tWgNK0HVHQfD9
+MDOkKGfUbqePjEKyf3W6HqlXk1d++fuz/ILJjvXJmMqpia/FD6jJJtZQS1XLITAd
+4e5bAAeeTaZ2BfM8oz1XN3CaZCMZrMFI0xIS+DKpoGWCn/n1fqXuBmWAdn170xlA
+6bl4xwWsHHhUiRktEcbrc0iZJxpb+vEsXIjK7OtH96lI4fYXtJCAMbDQNT4DPsfE
+MpOdV5PrYpCsvUgkiFSA4k7/hZJNVA==
+=WgFh
-----END PGP SIGNATURE-----
diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz
index 80034ea176..b4fb68dc89 100644
--- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz
+++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz
Binary files differ
diff --git a/timestamp b/timestamp
index 0343f0db74..d963d0ea89 100644
--- a/timestamp
+++ b/timestamp
@@ -2,4 +2,4 @@
# The source CTAN of this site's material:
dante.ctan.org
# The year-month-day-hour-minute of this site's material:
-2023-09-15-02-02
+2023-09-16-02-02